找到最近的n个地方

时间:2015-08-17 14:36:59

标签: sql-server tsql sql-server-2014

我正在使用这个简单的相关子查询来找到最接近某个地方的地方(当然是简化示例):

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个最近的地方。显然,相关的子查询在这种情况下不起作用。

1 个答案:

答案 0 :(得分:2)

如果我理解你的要求,我认为你应该可以使用这样的rank()窗口函数:

SELECT * FROM (
    SELECT 
       FromPlaceId,
       FromPlaceName,
       ToPlaceId,
       ToPlaceName,
       Distance,
       rank = RANK() OVER (PARTITION BY FromPlaceId ORDER BY Distance)
    FROM #temp  
) a
WHERE rank <= 2;

这将返回每个FromPlaceId的所有ToPlaceId,其距离最接近前两个,因此如果多个ToPlaceId具有相同的距离,则将返回所有ToPlaceId。

更改当前查询以在相关查询中使用intop 2也应该有效,但我认为窗口功能可能会更好。

FROM #temp AS a WHERE a.Distance IN
(
    SELECT TOP 2 b.Distance