有你需要做一些事情來使用MySQL地理空間擴展來完成這種事情。
- 您必須爲您的地理空間數據使用MyISAM表。
- 您需要在表中有一個
GEOMETRY
列,並且它必須是NOT NULL。
- 您不能使用問題中提到的球形餘弦定律距離計算作爲您的主要搜索條件。您需要使用邊界框(也就是說,您需要在搜索點的特定距離內搜索點)。
您當前的查詢通過檢查找到最靠近的點(37.77671,-122.3980)當你使用地理空間時,你做的事情比這更聰明一些,你需要建立一個接近極限,我們稱它爲10.0法定英里的半徑。有每北緯69.0度法定英里。
那麼,你如何做到這一切?
首先使自己與GE的表ometry列,或許是這樣的:
CREATE TABLE geoplace (
id INT NOT NULL,
geo GEOMETRY NOT NULL,
PRIMARY KEY id (id),
SPATIAL KEY geo (geo)
) ENGINE=MYISAM
然後填充它這樣的事情,把一個幾何Point
項目到每個geo
值。
INSERT INTO geoplace
SELECT DISTINCT id,
GEOMFROMTEXT(
CONCAT('POINT(',
lat,
' ',
lng,
')') ) AS geo
FROM places
當然,你可以把幾何列到你想要的任何表。但是你不能在InnoDB表中創建一個有效的空間索引;該訪問方法不支持空間索引。
然後,您需要這樣的查詢來檢索您的信息。
SELECT id, X(geo), Y(geo), distance FROM (
SELECT id, geo,r,
units * DEGREES(ACOS(
COS(RADIANS(latpoint))
* COS(RADIANS(X(geo)))
* COS(RADIANS(longpoint) - RADIANS(Y(geo)))
+ SIN(RADIANS(latpoint))
* SIN(RADIANS(X(geo))))) AS distance
FROM geoplace
JOIN (
SELECT 37.776708 AS latpoint, -122.398050 AS longpoint,
10.0 AS r, 69.0 AS units
) AS p ON (1=1)
WHERE MbrContains(GeomFromText(
CONCAT('LINESTRING(',
latpoint-(r/units),' ',
longpoint-(r /(units* COS(RADIANS(latpoint)))),
',',
latpoint+(r/units) ,' ',
longpoint+(r /(units * COS(RADIANS(latpoint)))),
')')), geo)
) AS d
WHERE distance <= r
ORDER BY distance
注意查詢的這個偉大的毛球使用您在本節中提供的參數:
SELECT 37.776708 AS latpoint, -122.398050 AS longpoint,
10.0 AS r, 69.0 AS units
它將使用MbrContains
做一個空間矩形搜索,然後計算它找到的點的距離使用球形餘弦定律公式,然後正確命令它們。與開始的查詢相比,這個事情運行得非常快,因爲它利用了空間索引。
這是寫在這裏更詳細。
http://www.plumislandmedia.net/mysql/using-mysqls-geospatial-extension-location-finder/
背景在這裏。
http://www.plumislandmedia.net/mysql/haversine-mysql-nearest-loc/