经常看到问题,如何取出每组的前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. jsfl 改变舞台宽高

    fl.getDocumentDOM().height= 680; fl.getDocumentDOM().width= 550;

  2. 前端-BootStrap

    bootstrap 英 /'buːtstræp/ 美 /'bʊt'stræp/ n. [计] 引导程序,辅助程序:解靴带 关于 BootCDN BootCDN 是 Bootstrap 中文网支持并维护 ...

  3. UI5-文档-4.28-Unit Test with QUnit

    现在我们在应用程序中有了一个测试文件夹,我们可以开始增加我们的测试覆盖率. 实际上,到目前为止我们添加到应用程序中的每个特性都需要单独的测试用例.到目前为止,我们完全忽略了这一点,所以让我们为步骤23 ...

  4. 递归实现tree JQuery

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  5. Several ports (8005, 8080, 8009) required by Tomcat v7.0 Server at localhost are already in use. The server may already be running in another process, or a system process may be using the port. To sta

    有三种导致这种错误的原因. 第一个: 是因为tomcat的服务没有被关闭所导致的,将服务关闭即可 找到tomcat的安装目录,进入bin文件夹,找到tomcat7w.exe,双击这个文件,点击stop ...

  6. POST方式"Content-type"是"application/x-www-form-urlencoded 的请求遇到的问题

    Content-type的方式:application/x-javascript text/xml->xml数据 application/x-javascript->json对象 appl ...

  7. 编写jQuery插件(一)——插件约定及插件中的闭包

    编写插件的目的是给已经有的一系列方法或函数做一个封装,以便在其他地方重复使用,提高开发效率和方便后期维护. 在编写jQuery插件的时候,我们一般会遵循一些约定: jQuery插件推荐命名为:jque ...

  8. Java操作Excel之Poi

    package com.java1234.poi; import java.io.FileOutputStream; import org.apache.poi.hssf.usermodel.HSSF ...

  9. [ERR] Not all 16384 slots are covered by nodes.

    redis集群开不起来,用redis-cli连接的时候出现如下错误: CLUSTERDOWN The cluster is down 然后使用redis-trib.rb检查: ./redis-trib ...

  10. Haskell语言学习笔记(22)MaybeT

    Monad Transformers Monad 转换器用于将两个不同的Monad合成为一个Monad.Monad 转换器本身也是一个 Monad. MaybeT MaybeT 这个 Monad 转换 ...