版权声明:本文为博主原创文章,未经博主允许不得转载。
经常看到问题,如何取出每组的前N条记录。方便大家参考于是便把常见的几种解法列出于下。
问题:有表 如下,要求取出各班前两名(允许并列第二)Table1+----+------+------+-----+| id |SName |ClsNo |Score|+----+------+------+-----+| 1 |AAAA | C1 | 67 || 2 |BBBB | C1 | 55 || 3 |CCCC | C1 | 67 || 4 |DDDD | C1 | 65 || 5 |EEEE | C1 | 95 || 6 |FFFF | C2 | 57 || 7 |GGGG | C2 | 87 || 8 |HHHH | C2 | 74 || 9 |IIII | C2 | 52 || 10 |JJJJ | C2 | 81 || 11 |KKKK | C2 | 67 || 12 |LLLL | C2 | 66 || 13 |MMMM | C2 | 63 || 14 |NNNN | C3 | 99 || 15 |OOOO | C3 | 50 || 16 |PPPP | C3 | 59 || 17 |QQQQ | C3 | 66 || 18 |RRRR | C3 | 76 || 19 |SSSS | C3 | 50 || 20 |TTTT | C3 | 50 || 21 |UUUU | C3 | 64 || 22 |VVVV | C3 | 74 |+----+------+------+-----+结果如下+----+------+------+-----+| id |SName |ClsNo |Score|+----+------+------+-----+| 5 |EEEE | C1 | 95 || 1 |AAAA | C1 | 67 || 3 |CCCC | C1 | 67 || 7 |GGGG | C2 | 87 || 10 |JJJJ | C2 | 81 || 14 |NNNN | C3 | 99 || 18 |RRRR | C3 | 76 |+----+------+------+-----+方法一:
select a.id,a.SName,a.ClsNo,a.Scorefrom Table1 a left join Table1 b on a.ClsNo=b.ClsNo and a.Score<b.Scoregroup by a.id,a.SName,a.ClsNo,a.Scorehaving count(b.id)<2order by a.ClsNo,a.Score desc方法二:
select *
from Table1 awhere 2>(select count(*) from Table1 where ClsNo=a.ClsNo and Score>a.Score)order by a.ClsNo,a.Score desc
方法三:
select *from Table1 awhere id in (select id from Table1 where ClsNo=a.ClsNo order by Score desc limit 2)order by a.ClsNo,a.Score desc
方法....这里列出了多种SQL语句的实现方法,有些是特有的(Limit, 其它可根据实际更改,比如的rownum,MS SQL SERVER 的 top,..),有时是SQL标准支持的。但效率上和应用的场合或许不同。具体应用时可根据实际表中的记录情况,索引情况进行选择。
特例 N=1 ,即取最大的/最小的一条记录。
+----+------+------+-----+| id |SName |ClsNo |Score|+----+------+------+-----+| 5 |EEEE | C1 | 95 || 7 |GGGG | C2 | 87 || 14 |NNNN | C3 | 99 |+----+------+------+-----+
select *
from Table1 awhere not exists (select 1 from Table1 where ClsNo=a.ClsNo and Score>a.Score);
select a.*
from Table1 a inner join (select ClsNo, max(Score) as mScore from Table1 group by ClsNo) b on a.ClsNo=b.ClsNo and a.Score=b.Score
select *
from (select * from Table1 order by Score desc) tgroup by ClsNo