【问题标题】:Calculation of Closest Distance of one table's IDs to another reference table without joining in reference table计算一个表的ID到另一个参考表的最近距离而不加入参考表
【发布时间】:2018-03-06 17:52:58
【问题描述】:

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

City_table 有每个城市的经纬度以及每个城市在人口方面的排名,ID_table 有每个 ID 的经纬度。我不能加入 City_table,因为我需要计算每个 ID 到每个城市的距离,并取其中的最小值。

以下计算获取从一个位置到另一个位置的距离并转换为英里:

(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

回顾一下,ID_table 有一个 ID、纬度和经度。 City_table 具有纬度、经度、城市和根据最高人口的排名。我需要从最接近 ID 位置的 City_table 获取城市的排名。

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

我正在尝试完成类似以下的事情(承认语法不正确,只是我认为我想要完成的想法)@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

【问题讨论】:

  • 任何尝试获得粗略版本?
  • @hastrb 是的,见上文,我编辑了原始问题以包含我认为我应该做什么的想法。
  • 两个建议。 1)使用地理类型 2)发布一个小样本和期望的结果。

标签: sql-server geolocation geocoding


【解决方案1】:

我强烈建议(正如 John Cappelletti 已经提到的)使用地理类型。我必须做和你类似的事情,我的参考表包含位置的地理位置。我将它加入到主查询“ON 1=1”中。这样,对于您的主查询的每一行,您都会从您的位置表中获得一个位置(请记住,如果您正在处理的表很大,这将很慢!)。无论如何,查询看起来像这样:

--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;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-25
    • 2017-08-24
    • 1970-01-01
    相关资源
    最近更新 更多