不使用三角函数的 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 距离查询的主要内容,如果未能解决你的问题,请参考以下文章

在 SELECT 语句中使用自定义函数时,为啥我的 SQL 查询的输出显示不正确?

MySQL:使用自定义函数计算经纬度之间的最短距离

T-SQL的高级查询语法

T-SQL高级查询语句

距离计算效率 MSSQL 地理

计算点之间的距离时不一致