您的位置:首页 > 数据库 > MySQL

MYSQL 分组取前N条数据

2016-09-20 21:53 302 查看
经常看到问题,如何取出每组的前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.Score
from Table1 a left join Table1 b on a.ClsNo=b.ClsNo and a.Score<b.Score
group by a.id,a.SName,a.ClsNo,a.Score
having count(b.id)<2
order by a.ClsNo,a.Score desc
方法二:
select *
from Table1 a
where 2>(select count(*) from Table1 where ClsNo=a.ClsNo and Score>a.Score)
order by a.ClsNo,a.Score desc
 
方法三:
select *
from Table1 a
where id in (select id from Table1 where ClsNo=a.ClsNo order by Score desc
limit 2)
order by a.ClsNo,a.Score desc
 
方法....

这里列出了多种SQL语句的实现方法,有些是MySQL特有的(Limit, 其它数据库可根据实际更改,比如oracle的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 a

where 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) t

group by ClsNo

转自:http://blog.csdn.net/acmain_chm/article/details/4126306
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: