查询数据库以查找区域中的位置

时间:2017-04-04 21:29:17

标签: php mysql maps geospatial geocoding

我有兴趣创建一个网站,该网站将存储多个位置,并且需要能够根据用户的查询找到它们。类似于Yelp,Zomato,Zillow等网站的功能。我首选的技术堆栈是PHP / MySQL。

那就是说,我有一些相关的问题。给定一个位置数据库及其关联纬度/经度坐标...

  1. 他们如何查询他们的位置数据库并返回特定城市或邮政编码X距离内的位置?
  2. 此外,他们如何查询他们的数据库中的位置,而不是在附近,是否在特定的城市或州限制范围内?他们从哪里获取边界数据?如何以有效的方式确定坐标是否在该边界内?
  3. 最后,我注意到有些网站在其网站上有特定于城市的链接。我希望从远程映射API中提取城市数据,但它们通常会将图像和其他内容与这些城市相关联。这些网站是否将所有城市的名称存储在自己的数据库中?他们从哪里获得他们的名单?

2 个答案:

答案 0 :(得分:0)

这将有助于您的第一点。

我使用此查询按距离起点搜索数据库中的属性。起点是经度和纬度$coordX$coordY。我从Google Maps API上进行地理编码查找得到了这些:

SELECT properties.*, 
    (
        (   ACOS(SIN(".$coordX." * PI() / 180) * 
            SIN(coordX * PI() / 180) + COS(".$coordX." * PI() / 180) * 
            COS(coordX * PI() / 180) * COS((".$coordY." - coordY) * 
            PI() / 180)) * 180 / PI()) * 60 * 1.1515
        ) 
    AS distance 
FROM properties 
order by distance

在我的表格中,我将各个属性坐标的坐标存储在coordXcoordY列中。

答案 1 :(得分:0)

这是MySQL函数,它将采用两个纬度/经度对,并给出两点之间的度数距离。 它使用Haversine公式计算距离。由于地球不是一个完美的球体,因此附近有一些误差 两极和赤道。

  • 要转换为里程,请乘以3961.
  • 要转换为公里数,请乘以6373。
  • 要转换为米,请乘以6373000。
  • 要转换为英尺,请乘以(3961 * 5280)20914080。

    DELIMITER $$

    创建功能haversine(         lat1 FLOAT,lon1 FLOAT,         lat2 FLOAT,lon2 FLOAT      )RETURNS浮动     没有SQL     确定性     评论'返回两个已知纬度和经度点之间地球上的度数。获得里程,乘以3961,乘以6373' 开始     返回度(ACOS(               COS(RADIANS(lat1))*               COS(RADIANS(lat2))*               COS(RADIANS(lon2) - RADIANS(lon1))+               SIN(RADIANS(lat1))* SIN(RADIANS(lat2))             )); END;

    DELIMITER;

使用FLOAT类型(10,6)将列添加到地址表中以获取纬度和经度。 编写一个php脚本,以便在保存记录时查找lat / long。

然后,您可以对表进行选择以获取具有距离的地址列表。你甚至可以排序 距离的结果,或将结果限制在参考位置的某个半径。

SELECT 
    `street`,
    `city`,
    `state`,
    `zip`,
    (haversine($ref_location_lat,$ref_location_long,`lat`,`long) * 3961) as `distance`
FROM `address_table`
WHERE (haversine($ref_location_lat,$ref_location_long,`lat`,`long) * 3961) < 300    //  Example for limiting returned records to a raduis of 300 miles.
ORDER BY haversine($ref_location_lat,$ref_location_long,`lat`,`long) DESC;      //  Don't need actual distance for sorting, just relative distance.