現(xiàn)在應用中類似 “優(yōu)先按距離排序” 的功能已經(jīng)很常見了讹语,那么這些功能如何簡單快速的去實現(xiàn)呢?本文將提供一個在數(shù)據(jù)量不是特別大的時候的解決方案蜂科,實現(xiàn)起來比較簡單顽决。
先將用來演示的表結構和數(shù)據(jù)初始化一下
-- 創(chuàng)建商戶表
CREATE TABLE merchant (
id int AUTO_INCREMENT COMMENT '主鍵',
merchant_name varchar(64) NOT NULL COMMENT '商戶名稱',
merchant_address varchar(64) NOT NULL COMMENT '商戶地址',
longitude double(15, 12) NOT NULL DEFAULT 0.0 COMMENT '經(jīng)度',
latitude double(15, 12) NOT NULL DEFAULT 0.0 COMMENT '緯度',
CONSTRAINT merchant_pk PRIMARY KEY (id)
) COMMENT '商戶表';
-- 插入一些測試數(shù)據(jù)
INSERT INTO merchant VALUES (1, '海底撈火鍋', '浦建路118號巴黎春天百貨F5', 121.52088, 31.20852);
INSERT INTO merchant VALUES (2, '河馬鮮生', '長寧路88號KiNG88廣場B1層', 121.42741, 31.22761);
INSERT INTO merchant VALUES (3, '望湘園', '川沙路5398號百聯(lián)川沙購物中心F3層', 121.69961, 31.18577);
INSERT INTO merchant VALUES (4, '小楊生煎', '川沙路4825號浦東商場B1層', 121.69775, 31.19509);
INSERT INTO merchant VALUES (5, '肯德基', '張江路625號1層B座', 121.61561, 31.20514);
然后套用 Haversine公式 直接用 MySQL 的函數(shù)去計算距離再排序。例如:假設我當前位置是 [31.202635, 121.654555] 查詢周邊的商家导匣,并且按距離排序才菠。
SELECT *, ACOS(
COS(RADIANS(31.202635)) *
COS(RADIANS(latitude)) *
COS(RADIANS(longitude) - RADIANS(121.654555)) +
SIN(RADIANS(31.202635)) *
SIN(RADIANS(latitude))
) * 6378 AS distance
FROM merchant
ORDER BY distance
LIMIT 0, 20;
其中 6378 是地球赤道的半徑,如果想調整精度贡定,比如精確到米赋访,可以設置為 6378000,下面是排序的結果
id | merchant_name | merchant_address | longitude | latitude | distance |
---|---|---|---|---|---|
5 | 肯德基 | 張江路625號1層B座 | 121.61561 | 31.20514 | 3.7185308288925247 |
4 | 小楊生煎 | 川沙路4825號浦東商場B1層 | 121.69775 | 31.19509 | 4.197812806482076 |
3 | 望湘園 | 川沙路5398號百聯(lián)川沙購物中心F3層 | 121.69961 | 31.18577 | 4.683026249493325 |
1 | 海底撈火鍋 | 浦建路118號巴黎春天百貨F5 | 121.52088 | 31.20852 | 12.744185472645878 |
2 | 河馬鮮生 | 長寧路88號KiNG88廣場B1層 | 121.42741 | 31.22761 | 21.802509499536363 |