正如@OllieJones 评论的那样,您需要使用haversine 公式来计算大圆距离。改编自 Google Code's Creating a Store Locator with PHP, MySQL & Google Maps以尽可能多地缓存:
ALTER TABLE Postcodes
ADD tc DOUBLE COMMENT 'cosine of latitude',
ADD ts DOUBLE COMMENT 'sine of latitude',
ADD gr DOUBLE COMMENT 'longitude in radians',
ADD UNIQUE INDEX (Postcode);
CREATE TRIGGER Postcode_insert BEFORE INSERT ON Postcodes FOR EACH ROW SET
NEW.tc = cos(radians(NEW.Latitude)),
NEW.ts = sin(radians(NEW.Latitude)),
NEW.gr = radians(NEW.Longitude);
CREATE TRIGGER Postcode_update BEFORE UPDATE ON Postcodes FOR EACH ROW SET
NEW.tc = cos(radians(NEW.Latitude)),
NEW.ts = sin(radians(NEW.Latitude)),
NEW.gr = radians(NEW.Longitude);
UPDATE Postcodes SET tc = NULL; -- trigger will do the rest
CREATE VIEW distance AS
SELECT s.Id AS PostID, u.Postcode,
acos(s.tc*u.tc*cos(s.gr-u.gr) + s.ts*u.ts) AS radii
FROM Postcodes s, Postcodes u;
那么你需要做的就是:
SELECT Locations.*, 3959 * distance.radii AS miles
FROM Locations JOIN distance USING (PostID)
WHERE distance.Postcode = ?
HAVING miles < ?
在sqlfiddle上查看。