1

我有两张表,一张包含英国的所有邮政编码以及它们的纬度和经度。第二个是带有商店位置的表。

我需要创建一个快速搜索查询,以从最近到最远的顺序返回用户指定半径内的所有商店(帖子)及其距离。

表结构为:

邮政编码表字段:ID、邮政编码、纬度、经度

位置表字段:商店名称、PostID、Lat、Lng

搜索将返回帖子名称和与该商店相关的信息摘录。

获取用户提交的邮政编码的查询,从 Postcodes 表中获取该邮政编码的纬度和经度,然后在 Postcodes 表纬度/经度和位置中的每个 Lat/Long 之间运行距离计算,返回那些在用户指定的距离是我想象的需要,但在创建两组 lat/lng 之间的距离计算时没有运气。

所需距离最多 10 英里、最多 20 英里、最多 50 英里、最多 100 英里和超过 100 英里。

非常感谢任何帮助。

非常感谢,

4

1 回答 1

1

正如@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上查看。

于 2012-09-16T11:32:15.600 回答