测量所有距离返回的最短值

时间:2018-12-19 19:55:48

标签: sql-server tsql

我有一张桌子,上面有商店的清单,大约有100个经纬度。第二个表中有一个客户列表,经/纬度超过50万。

我需要找到离每个客户最近的商店。目前,我正在将地理数据类型与STDistance函数一起使用,以计算两个点之间的距离。这个功能运行良好,但是我迷上了处理此问题的最有效方法。

选项#1-笛卡尔将Customer_table加入到Store_table,处理距离计算,对结果进行排名并过滤为#1。与此相关的是,如果您有100万行客户列表和100家商店,那么您将创建一个1亿行表,而排名函数则可能会增加负担。

选项#2-使用一些动态sql,创建一个数据透视表,该表在第一列中具有每个客户,而在随后的每一列中都具有到每个分支的计算距离。从那里,我可以取消透视,然后执行与第一个步骤相同的排名/结束功能。

示例

CUST_ID     LAT     LONG     STORE1DIST     STORE2DIST     STORE3DIST
1           20.00   30.00    4.5            5.6            7.8
2           20.00   30.00    7.4            8.1            8.5

我不清楚哪种方法最有效,并且会使DBA不想找我。

感谢您的预先输入!

2 个答案:

答案 0 :(得分:0)

您可以针对每个存储距离将数据取消旋转为多行,然后使用简单的旋转(分组依据)来获取StoreDistance的最小值。

select CUST_ID, MIN(STOREDIST) StoreDistance, MIN(STORES) StoreName
from 
(select CUST_ID, LAT, LONG, STORE1DIST, STORE2DIST, STORE3DIST from Cus/*Your table*/) p
UNPIVOT
(
STOREDIST FOR STORES IN (STORE1DIST, STORE2DIST, STORE3DIST)
) as unpvt
Group by CUST_ID

这将为您提供以下结果:

CUST_ID StoreDistance   StoreName
-----------------------------------
1       4.5             STORE1DIST
2       7.4             STORE1DIST

答案 1 :(得分:0)

我的工作也有类似情况。我使用这样的距离函数(返回公里,使用3960*返回英里):

CREATE Function MySTDistance(@lat1 float, @lon1 float, @lat2 float, @lon2 float)
returns smallmoney
as
    return IsNull(6373*acos((sin(radians(@lat1))*sin(radians(@lat2)))
                           +(cos(radians(@lat1))*cos(radians(@lat2))*cos(radians(@lon1-@lon2)))),0)

然后您通过执行以下操作来寻找最近的商店...

select C.Cust_Id
    ,Store_id=
        (select top (1) Store_id
           from Store_Table S
          order by dbo.MySTDistance(S.lat, S.long, C.lat, C.long)
        )
from Customer_Table C

现在,您有了每个客户ID及其最接近的商店ID。拥有大量客户的速度相当快(至少就我而言)。