Sqlserver:班级排名问题(转发)


id,name(人名),class(班级),fen(分数)
1  jj          1          88
2  j1          1            90
3  j2            2        70
选出每个班级头两名分数, 显示班级,人名,分数????????


create table #t (id int,name varchar(20),class varchar(10),fen int)
insert into #t
select 1,'jj','1',88 union all
select 2,'j1','1',90 union all
select 3,'j2','1',70 union all
select 4,'j3','2',89 union all
select 5,'ja','3',96 union all
select 6,'jb','3',63

解法一:
select *
from #t t
where (select count(*) from #t where class="t".class and fen > t.fen) =0 -- 第一名
where (select count(*) from #t where class="t".class and fen > t.fen) =1 -- 第二名
where (select count(*) from #t where class="t".class and fen > t.fen) <2 -- 前2名
where (select count(*) from #t where class="t".class and fen < t.fen) =0 -- 倒数第一名
where (select count(*) from #t where class="t".class and fen < t.fen) =1 -- 倒数第二名
where (select count(*) from #t where class="t".class and fen < t.fen) <2 -- 倒数前2名

解法二:
select t.* from #t t where fen in (select top 2 fen from #t where class = t.class) order by class,fen

解法三:
select *
from
(
select row_number() over(partition by  class order by fen desc) as rank,* from #t
) t
where rank <=2
order by class,rank,fen
附注:排名函数
rank():稀疏排名,排名可能会并列,因此引起排名的数字间断。如有两个并列第一,则接下来的排名为第三!
dense_rank():非稀疏排名,排名可能会并列,但排名的数字不会间断。如有两个并列第一,则接下来的排名为第二!
ntile(group count):(抽屉分配)将数据按分组数分组 分配。主要是看总行数 是否 能被 组数 平均分配,如果不能平均分配,则会将数据有限分配到前面的组中!
row_number():分配唯一的逻辑行记录的id,通常用于分页用 
over子句还支持聚合函数 和 窗口分区子句

解法四:
select distinct t.*
from #t a
cross apply (select top 2 * from #t b where a.class = b.class order by fen desc) as t --内部(左值)多值交叉表
order by t.class,t.fen desc


解法五:
select distinct t.*
from #t a
outer apply (select top 2 * from #t b where a.class = b.class order by fen desc) as t --外部(右值)多值交叉表
order by t.class,t.fen desc

原文地址:https://www.cnblogs.com/jinzhenshui/p/1621975.html