我有两张桌子,一张包含英国的所有邮政编码以及他们的纬度和经度。第二个是带商店位置的表格。
我需要创建一个快速搜索查询,按照从最近到最远的顺序返回用户指定半径内的所有商店(帖子)及其距离。
表结构是:
邮政编码表字段: Id,邮政编码,纬度,经度
地点表字段: 商店名称,PostID,Lat,Lng
搜索将返回帖子名称和与该商店相关的信息摘录。
获取用户提交的邮政编码的查询,从Postcodes表中获取其经度和纬度,然后在Postcodes表纬度/经度与位置中的每个Lat / Long之间运行距离计算,返回用户指定距离内的那些是我想象的必需,但是在两组lat / lng之间创建距离计算没有运气。
所需距离可达10英里,最长20英里,最长50英里,最长可达100英里,行程超过100英里。
任何帮助都非常感激。
非常感谢,
丹
答案 0 :(得分:1)
作为@OllieJones commented,您需要使用haversine formula来计算great circle distance。适应Google代码的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上查看。