簡體   English   中英

在MySQL中找到最接近的匹配十進制列

[英]Find closest match in MySQL on decimal columns

下午,

我在解決這個問題時遇到了一些困難。 我有一個MySQL表,其中包含英國郵政編碼及其經度和緯度值的列表。 我希望能夠在表格上進行搜索,以找到最接近給定長/短對的郵政編碼。

我一直在嘗試使用的查詢是:

"SELECT id, outcode AS thecode, @la := MATCH(lat) AGAINST(?) AS score_lat, @ln := MATCH(lng) AGAINST(?) AS score_lng, @la + @ln AS score_total FROM postcodes ORDER BY score_total DESC LIMIT 10

但是,這只會返回看似隨機的郵政編碼,例如,緯度:55.775549,長度:-4.047556

Array
(
[0] => Array
    (
        [id] => 929
        [thecode] => FK14
        [score_lat] => 0
        [score_lng] => 0
        [score_total] => 0
    )

[1] => Array
    (
        [id] => 2785
        [thecode] => UB3
        [score_lat] => 0
        [score_lng] => 0
        [score_total] => 0
    )

[2] => Array
    (
        [id] => 993
        [thecode] => G70
        [score_lat] => 0
        [score_lng] => 0
        [score_total] => 0
    )

[3] => Array
    (
        [id] => 2849
        [thecode] => WC2B
        [score_lat] => 0
        [score_lng] => 0
        [score_total] => 0
    )

[4] => Array
    (
        [id] => 1057
        [thecode] => GU29
        [score_lat] => 0
        [score_lng] => 0
        [score_total] => 0
    )

[5] => Array
    (
        [id] => 2913
        [thecode] => WS13
        [score_lat] => 0
        [score_lng] => 0
        [score_total] => 0
    )

[6] => Array
    (
        [id] => 1121
        [thecode] => HP20
        [score_lat] => 0
        [score_lng] => 0
        [score_total] => 0
    )

[7] => Array
    (
        [id] => 1185
        [thecode] => IG6
        [score_lat] => 0
        [score_lng] => 0
        [score_total] => 0
    )

[8] => Array
    (
        [id] => 1249
        [thecode] => IV25
        [score_lat] => 0
        [score_lng] => 0
        [score_total] => 0
    )

[9] => Array
    (
        [id] => 1313
        [thecode] => KA8
        [score_lat] => 0
        [score_lng] => 0
        [score_total] => 0
    )
)

數據庫的架構為:

CREATE TABLE `postcodes` (
  `id` int(11) NOT NULL auto_increment,
  `outcode` varchar(4) NOT NULL,
  `lat` varchar(20) NOT NULL,
  `lng` varchar(20) NOT NULL,
  PRIMARY KEY  (`id`),
  FULLTEXT KEY `lat` (`lat`),
  FULLTEXT KEY `lng` (`lng`)
) ENGINE=MyISAM AUTO_INCREMENT=2975 DEFAULT CHARSET=latin1 AUTO_INCREMENT=2975 ;

我希望有人能幫幫忙! 如果您需要更多信息,請詢問...

謝謝,

tip2tail

MySQL MATCH()函數用於全文搜索,以“匹配”字符串。 (因此它返回零值也就不足為奇了。)

如果“最接近”是指您要計算地圖上兩點之間的距離(以“烏鴉飛過”來衡量),並且坐標以(小數度)緯度和經度給出,那么您確實需要使用大圓距(GCD)計算。

http://en.wikipedia.org/wiki/Great-circle_distance

您可以跳過所有這些細節,僅使用我的實現即可。 下面是我的一條SQL語句的SELECT列表的摘錄,此表達式計算兩點之間的距離(以英里為單位)...

     , ACOS(
          COS(RADIANS( d2.latitude ))
        * COS(RADIANS( d1.latitude ))
        * COS(RADIANS( d2.longitude ) - RADIANS( d1.longitude ))
        + SIN(RADIANS( d2.latitude ))
        * SIN(RADIANS( d1.latitude ))
           )*3958.82 AS distance_miles

在此示例中, d1代表起點,而d2代表終點。 latitudelongitude作為DECIMAL值提供。

使用d1的單個“已知”點,我可以通過此表達式排序,以首先獲取“最接近”的d2 (對於多個原點,我可以d1.id ,然后再通過此表達式對每個d1首先獲得最接近的d2 。但是關於我的問題就足夠了...


我從您的問題中復制了查詢並進行了修改(如下)。 基本上,我刪除了“得分”列,並將其替換為執行距離計算的表達式:

SELECT id
     , outcode AS thecode
     , ACOS(
           COS(RADIANS( d2.latitude ))
         * COS(RADIANS( @d1_latitude ))
         * COS(RADIANS( d2.longitude ) - RADIANS( @d1_longitude ))
         + SIN(RADIANS( d2.latitude ))
         * SIN(RADIANS( @d1_latitude ))
           )*3958.82 AS distance_miles
  FROM postcodes d2
  JOIN (SELECT @d1_latitude := ?, @d1_longitude := ?) v
 ORDER BY distance_miles LIMIT 10

在這種情況下, @d1_變量(從綁定變量分配)是“已知”點的緯度和經度。 對於您的postcodes表中的每一行(為方便起見,我將其別名為d2 ),此表達式計算表中經緯度與“已知”點之間的距離。

注意:別名為v的內聯視圖就在那里,因此您可以綁定一次緯度,然后將值分配給可以引用的用戶變量。 該內聯視圖可以省略,您可以看到需要在哪里綁定兩次緯度。

注意:這將以“英里”為單位計算距離。 通過使用其他值代替3958.82常數,可以輕松獲得以千米(km)為單位的3958.82

注意:無需返回距離; 如果您只想按距離順序返回最接近的10個,則可以將該表達式放在ORDER BY子句中,例如

SELECT id
     , outcode AS thecode
  FROM postcodes d2
  JOIN (SELECT @d1_latitude := ?, @d1_longitude := ?) v
 ORDER
    BY ACOS(
           COS(RADIANS( d2.latitude ))
         * COS(RADIANS( @d1_latitude ))
         * COS(RADIANS( d2.longitude ) - RADIANS( @d1_longitude ))
         + SIN(RADIANS( d2.latitude ))
         * SIN(RADIANS( @d1_latitude ))
           )*3958.82 AS distance_miles
 LIMIT 10

如果您要尋找的不是兩點之間的距離,請讓我知道,因為在這種情況下,此答案對您沒有任何幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM