Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 选择最近点的最有效方法_Sql_Sql Server_Performance_Tsql_Geospatial - Fatal编程技术网

Sql 选择最近点的最有效方法

Sql 选择最近点的最有效方法,sql,sql-server,performance,tsql,geospatial,Sql,Sql Server,Performance,Tsql,Geospatial,我有两个结构相同的非常大的表,包含两种类型的位置: 失水事故 Id-INT 浮动纬度 Y-浮动经度 及 LocB Id-INT 浮动纬度 Y-浮动经度 他们每个人都有几百万排。我需要选择LocA中的所有位置,并为每个位置选择LocB中最近的位置 要做到这一点,最有效的查询是什么 EDIT1:距离算法将是一个愚蠢的算法:SQRTPOWERLocB.X-LocA.X,2+POWERLocB.Y-LocA.Y,2 EDIT2:我已经完成了一个实现,但我真的不确定它是否是最优的,我高度怀疑它,它将是:

我有两个结构相同的非常大的表,包含两种类型的位置:

失水事故 Id-INT 浮动纬度 Y-浮动经度 及

LocB Id-INT 浮动纬度 Y-浮动经度 他们每个人都有几百万排。我需要选择LocA中的所有位置,并为每个位置选择LocB中最近的位置

要做到这一点,最有效的查询是什么

EDIT1:距离算法将是一个愚蠢的算法:SQRTPOWERLocB.X-LocA.X,2+POWERLocB.Y-LocA.Y,2

EDIT2:我已经完成了一个实现,但我真的不确定它是否是最优的,我高度怀疑它,它将是:

SELECT  A.Id    AS AId,
(   SELECT TOP 1 B.Id
    FROM    B
    ORDER BY SQRT(POWER(B.X - A.X, 2) + POWER(B.Y - A.Y, 2)) ASC
)               AS BId
FROM    A
EDIT3:表LocB中存在重复项是很常见的,但我希望为LocA中的某个位置返回任何最接近的匹配项,而不是全部。

以下是代码:

WITH S AS (
SELECT *
FROM LOCA CROSS APPLY( select locb.id as ID_B, (POWER(LocB.X - LocA.X, 2) + POWER(LocB.Y - LocA.Y, 2)) D  FROM LOCB ) S
)
SELECT DISTINCT ID,X,Y,d,ID_B
FROM S
where d=(select min(d) from s s1 where s1.ID=s.id)

这可能不是很有效率,但目前我看不到更好的方法:

SELECT  a.ID, a.X, a.Y, b.ID, b.X, b.Y, b.Distance
FROM    LocA a
        CROSS APPLY
        (   SELECT  TOP 1 WITH TIES
                    b.ID, 
                    b.X, 
                    b.Y, 
                    Distance = SQRT(POWER(b.X - a.X, 2) + POWER(b.Y - a.Y, 2))
            FROM    LocB b 
            ORDER BY Distance
        ) B;
那么:

SELECT id as Aid,x,y,m % 100 as bId
FROM (
SELECT A.id,A.x,A.y,MIN(CAST(((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)) AS BIGINT)*100+B.id)     as m 
FROM A
CROSS JOIN B
GROUP BY A.id,A.x,A.y) j;

SQRT不会改变顺序-它只是开销

SELECT  A.Id AS AId,
(   SELECT TOP 1 B.Id
    FROM    B
    ORDER BY POWER(B.X - A.X, 2) + POWER(B.Y - A.Y, 2) ASC
)               AS BId
FROM    A
我认为有一种方法可以完成两次传球
你知道距离是你有没有想过要考虑,方法,并在这些点列上创建一个


如果您的数据库结构是固定的,您可以添加一个新的持久化计算列。

使用什么算法进行最接近?有many@Jamiec当前位置不要太早。我们仍在讨论10000000²的计算。您将如何处理等距点?返回所有匹配点?就一个?另外,这是一次性查询还是重复查询?我建议您检查一下此类查询。您最感兴趣的是这一特定页面:回答很好,但我认为OP想要的是最近的位置lat/long,而不是最小距离。是的,的确如此。我还需要LocB中位置的ID。不过,感谢您花时间构建它!为什么在从S选择不同ID,X,Y,MIND OVERPARTITION BY ID FROM S中使用窗口函数,而不是更传统的选择ID,X,Y,MIND FROM S GROUP BY ID,X,Y;?假设ID是主键,则两者是同义词,后者效率更高,在我看来更具可读性。这有一个问题,如果两个点的距离相同,则返回其中一个。@Amirezakeshavarz更正以解决关系问题,如果有联系,它将返回所有记录。这与OP的查询几乎相同-只是它提供了要添加的“带联系”选项。@Ypercurbe是的,在我开始回答时,编辑还没有完成,并且由于我页面上答案框的位置,我看不到指示问题已编辑的标志,因此,当我看到OP所写的内容时,我已经发布了答案。它还有一个额外的好处,即允许在单个查询中返回距离和ID,如果不是这样,我会删除它。这不会返回重复的距离。
create #temp1
IDa
IDb
Xa
Ya
Xb 
Yb 
distSum
distAct 

insert into #temp (IDa, IDb, Xa, Ya, Xb ,Yb, distSum)
select a.ID, b.ID, a.x, a.y, b.x, b.y, abs(a.X-b.X) + abs(a.Y-b.Y)
table as a 
join table as b 
on a.ID < b.ID 

delete #temp 
from #temp 
join 
(select IDa, min(distSum) as minDistSum from #temp group by IDa) as aMin 
on #temp.IDa = aMin.IDa 
and #temp.distSum > 1.414*(minDistSum) 

update #temp 
set distAct = POWER(Xa - Xb, 2) + POWER(Ya - Yb, 2)