经常看到问题,如何取出每组的前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

分组取前N记录的更多相关文章

  1. mysql分组取前N记录

    http://blog.csdn.net/acmain_chm/article/details/4126306 http://bbs.csdn.net/topics/390958705 1 我只用到了 ...

  2. php分享十二:分组取前N记录

    经常看到问题,如何取出每组的前N条记录 http://blog.csdn.net/acmain_chm/article/details/4126306 问题:有表 如下,要求取出各班前两名(允许并列第 ...

  3. 分组取前N记录(转)

    版权声明:本文为博主原创文章,未经博主允许不得转载. 经常看到问题,如何取出每组的前N条记录.方便大家参考于是便把常见的几种解法列出于下. 问题:有表 如下,要求取出各班前两名(允许并列第二)Tabl ...

  4. hive中分组取前N个值的实现

    背景 假设有一个学生各门课的成绩的表单,应用hive取出每科成绩前100名的学生成绩. 这个就是典型在分组取Top N的需求. 解决思路 对于取出每科成绩前100名的学生成绩,针对学生成绩表,根据学科 ...

  5. mysql学生成绩排名,分组取前 N 条记录

    转载  https://blog.csdn.net/jslcylcy/article/details/72627762 score表: CREATE TABLE `score` ( `student_ ...

  6. MongoDB 聚合分组取第一条记录的案例及实现

    关键字:MongoDB: aggregate:forEach 今天开发同学向我们提了一个紧急的需求,从集合mt_resources_access_log中,根据字段refererDomain分组,取分 ...

  7. Hive分组取第一条记录

    需求 交易系统,财务要求维护每个用户首个交易完成的订单数据(首单表,可取每个用户交易完成时间最老的订单数据).举例: 简写版的表结构: 表数据: 则 财务希望汇总记录如下: uid order_id ...

  8. SQL Server 2008 R2——分组取前几名

    =================================版权声明================================= 版权声明:本文为博主原创文章 未经许可不得转载  请通过右 ...

  9. mysql使用GROUP BY分组实现取前N条记录的方法

    MySQL中GROUP BY分组取前N条记录实现 mysql分组,取记录 GROUP BY之后如何取每组的前两位下面我来讲述mysql中GROUP BY分组取前N条记录实现方法. 这是测试表(也不知道 ...

随机推荐

  1. 0_Simple__simpleVoteIntrinsics + 0_Simple__simpleVoteIntrinsics_nvrtc

    介绍了线程束表决函数的实例(其概念介绍见 http://www.cnblogs.com/cuancuancuanhao/p/7841512.html),并在静态和运行时编译两种条件下进行使用. ▶ 源 ...

  2. robot framework取出列表子元素

    取出嵌套列表变量的子元素 ${list}型列表: ${list} = [["A1", "first"], ["A2", "seco ...

  3. leetcode166

    public class Solution { public String fractionToDecimal(int numerator, int denominator) { HashMap< ...

  4. json小知识

    json转换新方法 上面是把一个json数组转换成map集合 fromObject()是通用的 map集合,bean对象,String转换成json 文件转换成字符串,在转换成json 生成json文 ...

  5. Maven可执行jar包

    参考文章: Maven生成可以直接运行的jar包的多种方式(http://blog.csdn.net/xiao__gui/article/details/47341385) 一般,我们通过 > ...

  6. http chunked

    http chunked传输:将信息分段传输 好处: 不用指定content-length字段(总的要传输文件信息的长度),即可以将一整段信息分为若干段分别发送,最后发送chunked长度为0的信息表 ...

  7. How to Pronounce Ending T Clusters + Homophones — Baking!

    How to Pronounce Ending T Clusters + Homophones — Baking! Share Tweet Share Tagged With: ARE Reducti ...

  8. Haskell语言学习笔记(23)MonadReader, Reader, ReaderT

    MonadReader 类型类 class Monad m => MonadReader r m | m -> r where ask :: m r ask = reader id loc ...

  9. jQuery:总体掌握

    链式编程....方法多,属性无法得到对象进行链式.vs10自动完成.书籍锋利的jQuery vsdoc有智能提示开发时候用,开发完之后,换成min压缩版的. 经验:打开网站文件夹.可以把vs网站上的解 ...

  10. js判断第二个日期比第一个日期大

    如何用脚本判断用户输入的的字符串是下面的时间格式2004-11-21 必须要保证用户的输入是此格式,并且是时间,比如说月份不大于12等等,另外我需要用户输入两个,并且后一个要比前一个晚,只允许用JAV ...