我有一个sql查询,它根据一定范围内的坐标从数据库中提取位置。现在我试图通过接近一些数学来对它们进行排序 - 但无论我在纸上写出多少次,我似乎无法找到一个有效的解决方案。
让我们描述一些变量:
需要注意的一件大事是,我已经将所有坐标转换为正数,并且有另一个确定正面或负面的场地 - 但是为此我假设我已经正确地查询了附近的坐标。
为了以这种方式订购,我看到人们使用“ORDER BY abs(coord-coords)”来做一些简单的事情 - 但我需要的更像是:
[($ slat - $ plat)*($ slong - plong)] - 但是这会导致问题,因为如果一方产生的计算结果为零 - 那么在乘以之后结果也将为零 - 使其无效。
任何想法 -
答案 0 :(得分:1)
纬度/经度坐标之间距离的解决方案称为haversine formula。这很复杂,因为除非你的距离非常短,否则你需要考虑地球的曲率。
这是一篇关于使用PHP和MySQL实现定位器应用程序的文章:Creating a Store Locator with PHP, MySQL & Google Maps
您还可以在Stack Overflow上找到有关计算坐标之间距离的许多其他问题:https://stackoverflow.com/search?q=longitude+distance
如果你只需要计算5公里内的距离,那么地球的曲率可能并不显着。您可以使用普通distance formula。如果您只需要使用此值来排序哪一个更接近,您甚至可以跳过平方根计算。
SELECT s.location_id,
(s.lat-p.lat)*(s.lat-p.lat) + (s.long-p.long)*(s.long-p.long) AS distance_squared
FROM Locations s, Locations p
WHERE p.location_id = ?
ORDER BY distance_squared;
我选择的表格('locations')有纬度/经度坐标(让我们称之为$ plat和$ plong)。
不,那些是PHP变量。您需要计算数据库表每行的纬度/经度坐标的距离。
问题是SQL通常一次只能从一个行计算内容。因此,您需要将两行组合成一行,因此计算可以使用两个位置的坐标。您可以使用自联接执行此操作。这基本上是将每一行与同一个表中的另一行配对。这就是为什么我列出Locations
两次,并给它们两个不同的别名,s
和p
(技术术语是相关名称)。
如果您习惯使用PHP,请将此自连接视为与嵌套循环类似:
foreach ($locations as &$s) {
foreach ($locations as &$p) {
// calculate the distance between $s and $p
}
}
WHERE
子句将p
的行限制在您开始的位置(您将单个值替换为?占位符),因此它只是查询与所有对齐的一行表的行。
另一个提示:我跳过使用SQRT()
,因为没有必要按距离排序。也就是说,如果三个位置距离我10公里,15公里和20公里,那么我可以按100,225和400进行排序并获得相同的排序,就像我按10,15和20排序一样。优点是我'已经消除了计算平方根,这有点降低了我的查询成本。
答案 1 :(得分:0)
如果您想要精确测量它,可以使用haversine公式来计算纬度/经度对之间的距离。如果你只是用它来进行排序,那么你可以回到毕达哥拉斯公式来计算近似值,或者使用距离的平方(以消除平方根)。