SQL - 如何使用子记录获得前5个记录

时间:2015-07-27 01:39:09

标签: sql sql-server sql-server-2008

我有一个返回下表的查询

ID   SubId  Rate    Time
1    1      10.00   '00:00:10'
2    1      11.00   '00:00:15'
3    2      12.00   '00:00:20'
4    3      13.00   '00:00:25'
5    4      14.00   '00:00:30'
6    5      15.00   '00:00:35'
7    6      16.00   '00:00:40'

现在的问题是,我需要 SubId 所在的那些记录时间排行榜前5

ID   SubId  Rate    Time
1    1      10.00   '00:00:10'
2    1      11.00   '00:00:15'
3    2      12.00   '00:00:20'
4    3      13.00   '00:00:25'
5    4      14.00   '00:00:30'
6    5      15.00   '00:00:35'

我的方法

Select ID,SubId,Rate from Query1 where SubId In (Select Top 5 SubId from Query1)
--Time was not included in it

注意:请不要建议上面的答案,因为它需要使用查询两次,因为查询已经花费了太多时间来返回上述记录。

3 个答案:

答案 0 :(得分:1)

with x as 
(select row_number() over(order by time) as rn, * from tablename)
select ID,SubId,Rate from x where rn <=5

这将根据表格中的升序排列行号。您还可以按所需列进行分区和排序。此后,您可以从cte中选择所需的行号。

答案 1 :(得分:1)

如果您不想两次使用相同的查询,我建议您将结果插入临时表中。这样,您就不必执行两次复杂查询。

CREATE TABLE #TopFive(Id)
INSERT INTO #TopFive
    SELECT TOP 5 SubId FROM QueryId ORDER BY [Time] DESC

然后在随后的查询中,您只需使用临时表:

SELECT * FROM <tbl> WHERE subId IN(SELECT Id FROM #TopFive)

您还可以在临时表上添加NONCLUSTERED INDEX以增加性能:

CREATE NONCLUSTERED INDEX NCI_TopFive ON #TopFive(Id)

答案 2 :(得分:1)

我的回答与费利克斯的回答略有不同,但差别很小。我宁愿创建一个覆盖的 NC索引。这样,当I / O操作在线路上使用时,I / O操作会减少。

将结果存储在临时表中,并在SubID

上创建一个覆盖的非群集
Select ID, SubId, Rate, [Time]
INTO #results
FROM Query1


CREATE NONCLUSTERED INDEX IX_SubID ON #results(SubId) INCLUDE(Id, Rate, [Time])

SELECT A.ID, A.SubId, A.Rate, A.[Time]
FROM 
#results  A
JOIN
(SELECT TOP 5 SubID from #results order by [Time] desc)  B
on A.SubID  =   B.SubID