查找前 n 个最近的地方
Find top n closest places
我正在使用这个简单的相关子查询来查找离某个地方最近的地方(当然是简化的示例):
IF OBJECT_ID('tempdb..#Temp') IS NOT NULL DROP TABLE #Temp
CREATE TABLE #Temp
(
FromPlaceId INT NOT NULL,
FromPlaceName [NVARCHAR](255) NOT NULL,
ToPlaceId INT NOT NULL,
ToPlaceName [NVARCHAR](255) NOT NULL,
Distance FLOAT NOT NULL
)
INSERT INTO #Temp( FromPlaceId, FromPlaceName, ToPlaceId, ToPlaceName, Distance) VALUES ( 1, N'Place1' , 2 , N'Place2' , 1.0 )
INSERT INTO #Temp( FromPlaceId, FromPlaceName, ToPlaceId, ToPlaceName, Distance) VALUES ( 1, N'Place1' , 3 , N'Place3' , 2.0 )
INSERT INTO #Temp( FromPlaceId, FromPlaceName, ToPlaceId, ToPlaceName, Distance) VALUES ( 2, N'Place2' , 1 , N'Place1' , 1.0 )
INSERT INTO #Temp( FromPlaceId, FromPlaceName, ToPlaceId, ToPlaceName, Distance) VALUES ( 2, N'Place2' , 3 , N'Place3' , 13.0 )
INSERT INTO #Temp( FromPlaceId, FromPlaceName, ToPlaceId, ToPlaceName, Distance) VALUES ( 3, N'Place3' , 1 , N'Place1' , 2.0 )
INSERT INTO #Temp( FromPlaceId, FromPlaceName, ToPlaceId, ToPlaceName, Distance) VALUES ( 3, N'Place3' , 2 , N'Place2' , 13.0 )
SELECT * FROM #Temp
SELECT
a.FromPlaceId,
a.FromPlaceName,
a.ToPlaceId,
a.ToPlaceName,
a.Distance
FROM #temp AS a WHERE a.Distance =
(
SELECT TOP 1 b.Distance FROM #Temp AS b WHERE a.FromPlaceId = b.FromPlaceId
ORDER BY b.Distance ASC
)
我只是想知道如何获得最近的 2 或 3 个地点。显然,关联子查询在这种情况下不起作用。
如果我正确理解您的要求,我认为您应该能够像这样使用 rank()
window 函数:
SELECT * FROM (
SELECT
FromPlaceId,
FromPlaceName,
ToPlaceId,
ToPlaceName,
Distance,
rank = RANK() OVER (PARTITION BY FromPlaceId ORDER BY Distance)
FROM #temp
) a
WHERE rank <= 2;
这将 return 每个 FromPlaceId 的所有 ToPlaceId 的距离在前两个最接近的位置,因此如果多个 ToPlaceId 具有相同的距离,则所有 ToPlaceId 都将被 returned。
将您当前的查询更改为在相关查询中使用 in
和 top 2
也应该有效,尽管我认为 window 函数可能执行得更好。
FROM #temp AS a WHERE a.Distance IN
(
SELECT TOP 2 b.Distance
我正在使用这个简单的相关子查询来查找离某个地方最近的地方(当然是简化的示例):
IF OBJECT_ID('tempdb..#Temp') IS NOT NULL DROP TABLE #Temp
CREATE TABLE #Temp
(
FromPlaceId INT NOT NULL,
FromPlaceName [NVARCHAR](255) NOT NULL,
ToPlaceId INT NOT NULL,
ToPlaceName [NVARCHAR](255) NOT NULL,
Distance FLOAT NOT NULL
)
INSERT INTO #Temp( FromPlaceId, FromPlaceName, ToPlaceId, ToPlaceName, Distance) VALUES ( 1, N'Place1' , 2 , N'Place2' , 1.0 )
INSERT INTO #Temp( FromPlaceId, FromPlaceName, ToPlaceId, ToPlaceName, Distance) VALUES ( 1, N'Place1' , 3 , N'Place3' , 2.0 )
INSERT INTO #Temp( FromPlaceId, FromPlaceName, ToPlaceId, ToPlaceName, Distance) VALUES ( 2, N'Place2' , 1 , N'Place1' , 1.0 )
INSERT INTO #Temp( FromPlaceId, FromPlaceName, ToPlaceId, ToPlaceName, Distance) VALUES ( 2, N'Place2' , 3 , N'Place3' , 13.0 )
INSERT INTO #Temp( FromPlaceId, FromPlaceName, ToPlaceId, ToPlaceName, Distance) VALUES ( 3, N'Place3' , 1 , N'Place1' , 2.0 )
INSERT INTO #Temp( FromPlaceId, FromPlaceName, ToPlaceId, ToPlaceName, Distance) VALUES ( 3, N'Place3' , 2 , N'Place2' , 13.0 )
SELECT * FROM #Temp
SELECT
a.FromPlaceId,
a.FromPlaceName,
a.ToPlaceId,
a.ToPlaceName,
a.Distance
FROM #temp AS a WHERE a.Distance =
(
SELECT TOP 1 b.Distance FROM #Temp AS b WHERE a.FromPlaceId = b.FromPlaceId
ORDER BY b.Distance ASC
)
我只是想知道如何获得最近的 2 或 3 个地点。显然,关联子查询在这种情况下不起作用。
如果我正确理解您的要求,我认为您应该能够像这样使用 rank()
window 函数:
SELECT * FROM (
SELECT
FromPlaceId,
FromPlaceName,
ToPlaceId,
ToPlaceName,
Distance,
rank = RANK() OVER (PARTITION BY FromPlaceId ORDER BY Distance)
FROM #temp
) a
WHERE rank <= 2;
这将 return 每个 FromPlaceId 的所有 ToPlaceId 的距离在前两个最接近的位置,因此如果多个 ToPlaceId 具有相同的距离,则所有 ToPlaceId 都将被 returned。
将您当前的查询更改为在相关查询中使用 in
和 top 2
也应该有效,尽管我认为 window 函数可能执行得更好。
FROM #temp AS a WHERE a.Distance IN
(
SELECT TOP 2 b.Distance