在不加入参考表的情况下计算一个表的ID与另一个参考表的最近距离

时间:2018-03-06 17:52:59

标签: sql-server geolocation geocoding

对此真的感到困惑:所以我试图从https://gist.github.com/Miserlou/c5cd8364bf9b2420bb29的人口中获得城市的排名(我将其转换为csv并上传到我们的SQL服务器,让我们来看看) s称之为City_table)ID_table中的每个ID最接近。

City_table具有每个城市的纬度和经度以及每个城市在人口方面的排名,并且ID_table具有纬度和范围。每个ID的经度。我无法加入City_table,因为我需要计算每个ID到每个城市的距离,并采用最小值。

下面的计算得出从一个位置到另一个位置的距离并转换为英里数:

(ACOS(辐射(90-CAST(ID_table.GEO_LATITUDE AS REAL)))* COS(RADIANS(90-City_table.latitude))+ SIN(RADIANS(90-CAST(ID_table.GEO_LATITUDE AS REAL)) )* SIN(RADIANS(90-City_table.latitude))* COS(RADIANS(CAST(ID_table.GEO_LONGITUDE AS REAL) - (-City_table.longitude))))* 6371)* 0.621371

总结一下,ID_table有ID,纬度和经度。 City_table根据最高人口具有纬度,经度,城市和等级。我需要从City_table获得最接近ID位置的城市等级。

我真的不知道该怎么做,非常感谢任何帮助。

我试图完成以下内容(承认语法不对,只是我认为我想要完成的想法)@hastrb

SELECT A.ID,City_table.rank,
       FOR EACH CITY IN City_table{(ACOS(COS(RADIANS(90-CAST(ID_table.GEO_LATITUDE AS REAL)))*COS(RADIANS(90-City_table.latitude))+
       SIN(RADIANS(90-CAST(ID_table.GEO_LATITUDE AS REAL)))*SIN(RADIANS(90-City_table.latitude)) *
       COS(RADIANS(CAST(ID_table.GEO_LONGITUDE AS REAL)-(-City_table.longitude))))*6371)*0.621371} AS DISTANCE
FROM ID_table A
WHERE ROW_NUMBER()OVER(PARTITION BY A.ID ORDER BY DISTANCE ASC) = '1'

所以我最终搞清楚这一点,但是为了将来参考,如果有人遇到同样的问题,我想出了一个解决方案(尽管可能不是最好的解决方案),但它有效:

WITH X
AS
(
SELECT A.ID, A.CITY, A.[STATE], B.[Rank], B.City AS CITY_TABLE_CITY, B.State AS CITY_TABLE_STATE,

       ((ACOS(COS(RADIANS(90-CAST(A.GEO_LATITUDE AS REAL)))*COS(RADIANS(90-B.latitude))+   
                                SIN(RADIANS(90-CAST(A.GEO_LATITUDE AS REAL)))*SIN(RADIANS(90-B.latitude))*
                                COS(RADIANS(CAST(A.GEO_LONGITUDE AS REAL)-B.longitude)))*6371)*0.621371) AS DISTANCE,

       ROW_NUMBER()OVER(PARTITION BY A.ID ORDER BY((ACOS(COS(RADIANS(90-CAST(A.GEO_LATITUDE AS REAL)))*COS(RADIANS(90-B.latitude))+   
                                SIN(RADIANS(90-CAST(A.GEO_LATITUDE AS REAL)))*SIN(RADIANS(90-B.latitude))*
                                COS(RADIANS(CAST(A.GEO_LONGITUDE AS REAL)-B.longitude)))*6371)*0.621371) ASC) AS DISTANCE_NUMBER
FROM ID_TABLE A
FULL OUTER JOIN CITY_TABLE B ON B.latitude<>A.GEO_LATITUDE
)
SELECT * 
FROM X
WHERE DISTANCE_NUMBER='1' AND DISTANCE IS NOT NULL
ORDER BY ID

1 个答案:

答案 0 :(得分:0)

我强烈建议(如John Cappelletti所述)使用地理位置类型。我必须做与您相似的事情,其中​​我的参考表包含位置的地理位置。我将其加入主查询“ ON 1 = 1”。这样,对于主查询的每一行,您将从Locations表中获得一个位置(请记住,如果要处理的表很大,那将会很慢!)。无论如何,查询看起来都是这样的:

--The next line declares a reference location (some lat/long example)!
DECLARE @reference_point geography=geography::STGeomFromText('POINT(-84.206230 33.897247)', 4326);

SELECT t.LocationName,
       t.PointGeom.STDistance(@reference_point) / 1609.34 AS [DistanceInMiles]
FROM
(
    SELECT LocationName,
           geography::Point(ISNULL(Geom.STY, 0), ISNULL(Geom.STX, 0), 4326) AS [PointGeom],
           Geom,
           Geom.STX AS [Longitude],
           Geom.STY AS [Latitude]
    FROM MyLocationsTable
) AS t;