不使用三角函数的 SQL 距离查询
Posted
技术标签:
【中文标题】不使用三角函数的 SQL 距离查询【英文标题】:SQL Distance Query without Trigonometry 【发布时间】:2011-07-01 13:57:58 【问题描述】:我有一个不支持三角函数的 SQLite 数据库。与第二个 lat,lng 对相比,我想按距离对表中的一组 lat,lng 对进行排序。我熟悉按距离对 lat、lng 对进行排序的标准半正弦距离公式。
在这种情况下,我并不特别关心精度,我的点之间的距离很远,所以我不介意将曲线视为直线来四舍五入。
我的问题,这种查询是否有一个普遍接受的公式?记住不要使用三角函数!
【问题讨论】:
你能不能分别得到 lat 和 long 的距离(绝对值),然后应用 pythag(那里没有触发)得到一个代表点之间距离长度的数字。如果这是垃圾,请忽略我 - 不太了解地理,但令我震惊的是,您可以将所有内容都视为三角形。 【参考方案1】:如果您的点彼此之间的距离在合理范围内(即不跨越半个世界,也不跨越日期变更线),您可以修正纬度和经度之间的差异(因为经度更短,除了在赤道),然后就像地球是平的一样计算距离。
由于您只想对值进行排序,因此您甚至不必使用平方根,只需将差异的平方相加即可。
例如,@lat
和 @lng
是您当前的位置,2
是差异校正:
select *
from Points
order by (lat - @lat) * (lat - @lat) + ((lng - @lng) * 2) * ((lng - @lng) * 2)
您可以将特定纬度的差异校正计算为1 / cos(lat)
。
Cees Timmerman 提出了这个公式,它也适用于日期变更线:
pow(lat-lat2, 2) + pow(2 * min(abs(lon-lon2), 360 - abs(lon-lon2)), 2)
【讨论】:
@downvoter:为什么要投反对票?如果你不解释你认为错误的地方,它就无法改进答案。 我也不明白为什么这个答案也有人反对。请解释一下。pow(lat - @lat, 2) + pow(2 * (lon - @lon), 2)
更短且与语言变量不同,但校正纬度的最终查询是什么?这是否有可能的俄罗斯-阿拉斯加问题?
@CeesTimmerman:校正纬度的是2 *
。例如,阿拉斯加的校正值在 1.6 到 3.2 之间,具体取决于纬度。
只要你不越过两极,pow(lat - lat2, 2) + pow(2 * min(abs(lon - lon2), abs((180 - abs(lon)) + (180 - abs(lon2)))), 2)
应该可以。 (14400.0 从斯特林到俄罗斯。)【参考方案2】:
如果您想在模型中使用适当的空间数据,请使用 SpatiaLite,它是一种支持空间的 SQLite 版本:
http://www.gaia-gis.it/spatialite/
它就像 PostGIS 是为 PostgreSQL 的。您的所有 SQLite 功能都将完美运行且不变,您还将获得空间功能。
【讨论】:
谢谢,这很有趣,但我不确定此时是否要更改我的数据库连接器。为这个很酷的链接点赞! 但这是正确的做法。你现在应该咬紧牙关,继续做一些真正有空间感的事情——以后的痛苦是值得的【参考方案3】:您总是可以截断正弦的Taylor series expansion 并使用 sin^2(x)+cos^2(x)=1 的事实来获得余弦的近似值。唯一棘手的部分是using Taylor's theorem to estimate the number of terms that you'd need for a given amount of precision。
【讨论】:
我希望我明白你在说什么。 图片不错!弧度(度 % 180)和 7 个术语看起来不错,对吧? 我在 Python 中修复了 this,但对于 180 和 -180,它仍然有 0.5 的折扣。【参考方案4】:用“/”更改“*”对我有用:
选择 * 从点 按 (lat - @lat) * (lat - @lat) + ((lng - @lng) / 2) * ((lng - @lng) / 2) 排序
【讨论】:
以上是关于不使用三角函数的 SQL 距离查询的主要内容,如果未能解决你的问题,请参考以下文章