【问题标题】:Making query to find nearest multiple(Lat,Long) from the single(Lat,Long)查询从单个(Lat,Long)中找到最近的多个(Lat,Long)
【发布时间】:2019-02-11 17:17:06
【问题描述】:

我正在从一个点进行最近点查询。这是顺序。 我在 MSSQLServer 中存储了多个 POI,表为 dbo.Place。第二个表是dbo.Position,它将存储收集到的 GPS 点。

我正在使用存储过程,并且位置的 LatLong 已定义且可用。如何根据以下示例进行查询?

dbo.Place

Id   | Name   | Lat   | Long
1      POI1     1.735   4.73225
2      POI2     1.5665  3.9983
3      Tim2     1.4344  3.1282

Lat Long 变量在存储过程中定义。我想用下面的公式来找到最近的点,我只会从3个查询中取最近的值(假设样本数据是3行)

SQRT(POW(X(`POI.Lat`) - 49.843317 , 2) + POW(Y(`POI.Long`) - 24.026642, 2)) * 100

谢谢。

【问题讨论】:

  • SQL Server 已经具有空间类型和功能。检查Query Spatial Data for Nearest Neighbor。不过,对于简单的点,使用例如where Lat between targetLat-tolerand and targetLon + tolerance 仅选择目标周围的 POI 可能更快,然后才计算距离。您可以在 Lat 和 Lon 字段上使用简单的索引来加快 Lat、Lon 字段的范围搜索

标签: sql sql-server spatial


【解决方案1】:

您可以为此使用 SQL Server 的地理函数。

DECLARE @InputLatitude FLOAT = 1.64
DECLARE @InputLongitude FLOAT = 4.25

DECLARE @GPS GEOGRAPHY = GEOGRAPHY::Point(@InputLatitude, @InputLongitude, 4326)

SELECT TOP 1
    P.*,
    Distance = @GPS.STDistance(GEOGRAPHY::Point(P.Lat, P.Long, 4326))
FROM
    dbo.Place AS P
ORDER BY
    @GPS.STDistance(GEOGRAPHY::Point(P.Lat, P.Long, 4326)) ASC

您应该考虑在已经转换 GPS 点的表格上添加 GEOGRAPHY 列,并添加 SPATIAL INDEX 以加快查询速度。

【讨论】:

  • 谢谢@EzLo。这是我需要的,它正在工作。但这是距离的不足。如何添加最近 POI 和 inputLatLong 之间的计算距离?
  • @encikpiee 只需将距离计算添加为列表达式。我已经编辑了答案。
  • 太棒了!谢谢@EzLo。问题解决了。感谢您的意见。上帝保佑你先生。
【解决方案2】:

除了推荐的地理类型外,您还可以使用浮点等常规数据类型获得类似的结果。

DECLARE @latitude FLOAT = 4.5678; -- Latitude of the place to search around
DECLARE @longitude FLOAT = 51.234; -- Longitude of the place to search around
DECLARE @range FLOAT = 100000; -- Max range in meters

SELECT TOP(1000)
    [place].[Lat],
    [place].[Long],
    ((((ACOS((SIN((PI() * [place].[Lat]) / 180.0) * SIN((PI() * @latitude) / 180.0)) + ((COS((PI() * [place].[Lat]) / 180.0) * COS((PI() * @latitude) / 180.0)) * COS((PI() * ([place].[Long] - @longitude)) / 180.0))) * 180.0) * 60.0) * 1.1515) * 1609.344) / PI() AS [Distance]
FROM [dbo].[Place] AS [place]
WHERE (((((ACOS((SIN((PI() * [place].[Lat]) / 180.0) * SIN((PI() * @latitude) / 180.0)) + ((COS((PI() * [place].[Lat]) / 180.0) * COS((PI() * @latitude) / 180.0)) * COS((PI() * ([place].[Long] - @longitude)) / 180.0))) * 180.0) * 60.0) * 1.1515) * 1609.344) / PI()) <= @range
ORDER BY [Distance]

【讨论】:

  • 应用任何函数阻止服务器使用任何索引。索引将有助于范围搜索,例如将单点转换为“框”,可用于在计算距离之前过滤 POI。 WHERE place.lat between @latitude - @delta and @latitude + @delta
  • 我的错误。编辑了答案。
  • SQL 服务器执行计划在查询中确实包含索引。但是,我不确定这对性能是否有太大意义。
  • 是搜索还是扫描?优化器将扫描整个索引,如果它可以在那里找到它想要的东西。
猜你喜欢
  • 1970-01-01
  • 2018-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多