在SQL Server中,如何在一个距离坐标小于20英里的表中返回值?

时间:2015-10-28 20:04:20

标签: sql sql-server

这是我一整天都在努力解决的一个非常有趣的问题。我有一张表,其中包含位置的ID,纬度和经度。这是来自更大位置的位置的子集。

我要做的是使用这个位置子集,并且对于每个位置,使用空中距离返回距离较大集合20英里内的位置。我的问题不在于计算空中距离,这是有效的,我的问题是如何在每一行上操作,如For循环,但使用基于集合的方法。

所以让我们说这是我的子集表LocationSubset

+----+---------+----------+
| ID |   Lat   |    Lon   |
+----+---------+----------+
| 1  | 41.0575 | -92.1364 |
+----+---------+----------+
| 2  | 47.0254 | -92.5723 |
+----+---------+----------+
| 3  | 38.9897 | -88.7623 |
+----+---------+----------+

我正在寻找更大的桌子,地点

+----+---------+-----------+
| ID |   Lat   |    Lon    |
+----+---------+-----------+
| 1  | 41.0575 | -92.1364  |
+----+---------+-----------+
| 2  | 47.0254 | -92.5723  |
+----+---------+-----------+
| 2  | 38.9897 | -88.7623  |
+----+---------+-----------+
| 4  | 36.2137 | -91.6528  |
+----+---------+-----------+
| 5  | 39.2643 | -123.0073 |
+----+---------+-----------+
| 6  | 39.941  | -123.0073 |
+----+---------+-----------+
| 7  | 35.7683 | -91.6528  |
+----+---------+-----------+
| 8  | 45.8406 | -91.6528  |
+----+---------+-----------+

让我们假设,使用Haversine公式,位置5和6位于位置1的20英里内,位置4和8位于位置2的20英里范围内。

我希望返回这样的内容:

+----+------------+----------+
| ID | LocationID | Distance |
+----+------------+----------+
| 1  | 5          | 15.4     |
+----+------------+----------+
| 1  | 6          | 16       |
+----+------------+----------+
| 2  | 4          | 17.4     |
+----+------------+----------+
| 2  | 8          | 2.5      |
+----+------------+----------+

每个位置可能在20英里内有零到多个位置,我试图在另一个表中捕获它。

如有必要,我可以添加说明。谢谢你的时间。

3 个答案:

答案 0 :(得分:6)

SELECT 
     LS.ID, 
     L.ID as LocationID, 
     MS_DISTANCE (LS.Lat , LS.Lon, L.Lat , L.Lon) as Distance
FROM LocationSubset LS
JOIN Locations L 
  ON MS_DISTANCE (LS.Lat , LS.Lon, L.Lat , L.Lon) < 20
 AND LS.ID <> L.ID    -- if you want remove comparasion with same object

但是你可以更好地使用sql server空间函数,因为那些允许使用空间索引。 Spatial Data

答案 1 :(得分:2)

SELECT subtable.ID as ID1, subtable.Lat as Lat1, subtable.Lon AS Lon1,
    Locations.ID as ID2, Locations.Lat as Lat2, Locations.Lon AS Lon2,
    (CalculatedDistance using Lat1,Lon1,Lat2,Lon2) AS Distance
FROM subtable CROSS JOIN maintable
WHERE (CalculatedDistance using Lat1,Lon1,Lat2,Lon2)<20

subtable生成子表的查询/视图

答案 2 :(得分:1)

您可能希望排除匹配的记录,因此请在您的加入中使用,然后交叉应用距离函数

SELECT ls.Id,
       l.Id LocationID,
       d.Distance
FROM   LocationSubset ls 
       JOIN Location l ON ls.Id <> l.Id
       CROSS APPLY (SELECT dbo.MS_DISTANCE(ls.Lat, ls.Lon, l.Lat, l.Lon) Distance) d
WHERE  d.Distance < 20