在Sql Sever 2008 中,如果需要查询每门课程的前3名,实现方法如下:
现有成绩表(Result),列(StudentNo学号,SubjectNo 科目编号,StudentResult学员成绩)
方法一:
SELECT distinct b.* FROMresult AS r
CROSS APPLY(
SELECT TOP(3) *FROM Result WHERE r.SubjectNo= SubjectNo ORDER BY StudentResult DESC ) AS b
order by SubjectNo, StudentResult desc
CROSS APPLY() 使用 APPLY 运算符可以为实现查询操作的外部表表达式返回的每个行调用表值函数。表值函数作为右输入,外部表表达式作为左输入。通过对右输入求值来获得左输入每一行的计算结果,生成的行被组合起来作为最终输出。APPLY 运算符生成的列的列表是左输入中的列集,后跟右输入返回的列的列表
方法二:
select * from(
select rnk=dense_rank() over(partition by subjectno ORDER BY studentresultDESC),*
from Result
) as t
where rnk <= 3 --各班各科前3名
dense_rank() 返回结果集分区中行的排名,在排名中没有任何间断,如果值相同,序列有并列情况。行的排名等于所讨论行之前的所有排名数加一。
over()中
<partition_by_clause>
将FROM 子句生成的结果集划分为数个应用 DENSE_RANK 函数的分区
<order_by_clause>
确定将DENSE_RANK 值应用于分区中各行的顺序。整数不能表示排名函数中使用的<order_by_clause> 中的列。
方法三:
select * from (
select ROW_NUMBER() over(partition by subjectno order by StudentResultdesc)as c ,* from result
) as t
where c<=3
ROW_NUMBER()返回结果集分区内行的序列号,每个分区的第一行从 1 开始
over()中,与方法二同理。
第二种写法有并列情况的考虑,也就是说如果有科目的成绩有2个并列第 3名,则此科目能查询出 4条记录。