对表中数据分组,有时只需要某列的聚合值;有时却需要返回整行数据,常用的方法有:子查询、ROW_NUMBER、APPLY,总体感觉还是ROW_NUMBER比较直观。
测试数据:

if OBJECT_ID('testGroup') is not null
drop table testGroup
GO
create table testGroup
(
ID int identity primary key,
UserID int,
OrderID int
)
GO
insert testGroup
select 1,10 union all
select 1,20 union all
select 1,30 union all
select 2,100 union all
select 2,200 union all
select 3,1000 union all
select 3,2000 union all
select 3,3000 union all
select 3,4000

一. 取分组中第1行(最大/最小值)
1. 取出分组中某列最大/最小值,不要求显示其他列
最常见的分组聚合,用group by 分组时,只有参加分组/聚合的列才可以被显示。

select UserID, MAX(OrderID) as MaxOrderID
from testGroup
group by UserID

2. 取出分组中某列最大/最小值,要求显示其他列

要显示表中其他列,用group by 不好实现,可以借助子查询。

select * from testGroup a
where ID = (select MAX(ID) from testGroup b where a.UserID = b.UserID)
order by ID
--或者
select * from testGroup
where ID in (select MAX(ID) from testGroup group by UserID)
--或者
select * from testGroup as a
where a.ID in (select top 1 ID from testGroup b where a.UserID = b.UserID order by b.OrderID desc)
--或者
select * from testGroup a
where not exists(select 1 from testGroup b where a.UserID = b.UserID and a.OrderID < b.OrderID)
--或者
select * from testGroup a
where (select count(1) from testGroup b where a.UserID = b.UserID and a.id <= b.id) = 1

二. 取分组中前N行(排名前几名)
前N行为正向排序(ASC),后N行改为反向排序(DESC)即可,N=1时也就是取最大/最小值的行。下面以前2名(N=2)为例。
1. SQL Server 2000的写法
(1)子查询

select * from testGroup as a
where a.ID in (select top 2 ID from testGroup b where a.UserID = b.UserID order by b.OrderID)
--或者
select * from testGroup a
where not exists (select 1 from testGroup b where a.UserID = b.UserID and a.OrderID > b.OrderID
having count(1) >= 2)
--或者
select * from testGroup a
where (select count(1) from testGroup b where a.UserID = b.UserID and a.ID >= b.ID) <= 2
--没有唯一标识的表,可以用checksum来标识每行
select * from testGroup as a
where checksum(*) in (select top 2 checksum(*) from testGroup b where a.UserID = b.UserID order by b.OrderID)

2. SQL Server 2005新语法

(2) ROW_NUMBER()

select ID, UserID, OrderID
from
(select *, ROW_NUMBER() over(partition by UserID order by OrderID) num
from testGroup ) t
where t.num between 1 and 2

(3) APPLY(TOP)

select distinct t.* from testGroup a
cross apply (select top 2 ID, UserID, OrderID from testGroup b
where a.UserID = b.UserID order by b.OrderID) as t

三. 取分组中第N行(排名第N名)
把上面的查询中,范围值都改为固定值,就可以取具体某一行了,下面以第3名(N=3)为例。
(1) 子查询

select * from testGroup a
where (select count(1) from testGroup b where a.UserID = b.UserID and a.OrderID >= b.OrderID) = 3
--或者
select * from testGroup a
where exists (select 1 from testGroup b where a.UserID = b.UserID and a.OrderID >= b.OrderID
having count(1) = 3)

(2) ROW_NUMBER()

select ID, UserID, OrderID
from
(select *, ROW_NUMBER() over(partition by UserID order by OrderID) num
from testGroup ) t
where t.num = 3

05. 取SQL分组中的某几行数据的更多相关文章

  1. 取SQL分组中的某几行数据

    取SQL分组中的某几行数据 对表中数据分组,有时只需要某列的聚合值:有时却需要返回整行数据,常用的方法有:子查询.ROW_NUMBER.APPLY,总体感觉还是ROW_NUMBER比较直观.测试数据: ...

  2. 取SQL分组中某几行数据

    常用的方法有:子查询.ROW_NUMBER.APPLY,总体感觉还是ROW_NUMBER比较直观 if OBJECT_ID('testGroup') is not null drop table te ...

  3. sql-实现select取行号、分组后在分组内排序、每个分组中的前n条数据

    表结构设计: 实现select取行号 sql局部变量的2种方式 set @name='cm3333f'; select @id:=1; 区别:set 可以用=号赋值,而select 不行,必须使用:= ...

  4. 在mysql中使用group by和order by取每个分组中日期最大一行数据

    转载自:https://blog.csdn.net/shiyong1949/article/details/78482737 在mysql中使用group by进行分组后取某一列的最大值,我们可以直接 ...

  5. ORACLE 中rownum和row_number()的使用区别(可指定取sql结果集的第几个数据)

    这篇文章主要介绍了oracle中rownum和row_number()的使用方法以及区别和联系,十分的详细,有需要的小伙伴可以参考下.   row_number()over(partition by ...

  6. mysql先分组,然后取每个分组中的第2大的记录

    文章参考http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/ 首先建表: ...

  7. 统计mysql库中每张表的行数据

    修改数据库配置文件:vim /etc/my.cnf [client] user=username password=password 使用shell脚本统计表中的行数据:count.sh #!/bin ...

  8. 在csv表格中修改/追加某行数据

    思路: 文本文件不能随意穿插信息,但是通过使用Seek()方法,可以在读取文本文件中移动光标从而修改所要修改的行. 思路步骤: 1.读取文件,打开csv文件,获取文件流,seek移动光标到开始, fo ...

  9. SQL SERVER 中 实现主表1行记录,子表多行记录 整合成一条虚拟列

    表中有这样的记录,简单的主子表,现要想通过left join 语句把两表关联起来 select * from tbl_diary_reback a left join tbl_diary_reback ...

随机推荐

  1. C# 实现无标题栏窗体点击任务栏图标正常最小化或还原的解决方法

    /// <summary> /// 实现窗体的最小化 /// </summary> protected override CreateParams CreateParams { ...

  2. How Tomcat Works(三)

    上文中描述的简单的服务器是不符合Servlet规范的,所以本文进一步描述一个简单的Servlet容器是怎么实现的 所以我们首先要明白Servlet接口规范,规范有不同版本,本人就先一视同仁了: pub ...

  3. halcon的性能

    ·满足您各类机器视觉应用需求的完善的开发库 ·包含匹配,识别,定位及1D,2D,3D测量等多种高级算法 ·强大,易用的工具加速您的开发进程 ·与Linux/UNI及Windows(包括×64)兼容,避 ...

  4. 修改IIS7中ASP的上传文件大小限制

    最近在处理一个ASP的项目,用的全新的Windows Server 2008服务器. 今天客户反映图片文件上传不上去,设置服务器端文件夹权限之后文件可以上传了. 但是不久客户就反映有几个文件传不上去, ...

  5. 利用HTML5开发Android(3)---Android中的调试

    通过JS代码输出log信息 Js代码 Js代码: console.log("Hello World"); Log信息: Console: Hello World http://ww ...

  6. 修改SVN账户密码的方法

        Case1:     在Eclipse 使用SVN 的过程中大多数人往往习惯把访问SVN 的用户名密码自动保存起来以便下次自动使用,不要再次手工输入,但是有些时候需要变更密码或者用户名,这时候 ...

  7. 微软自带报表rdlc操作(合并同数据项)

    一.使用table合并数据项(隐藏相同数据项). 1.添加table,添加各数据项目和表头. 2.添加分组,选中table1右键属性->组->添加. 3.右键需要隐藏数据项的列->属 ...

  8. radvd.conf RADVD配置文件内容部分解析

    interface eth0{ AdvSendAdvert on; #启用路由器公告(RA)功能 MinRtrAdvInterval ; #每隔30-100秒间隔发送公告消息 MaxRtrAdvInt ...

  9. Java学习笔记之接口

    一.接口的概念与定义 首先考虑一个简单的接口的定义: public interface Output { int MAX_LINE = 40; void out(); void getData(Str ...

  10. UVALive 4223 Trucking 二分+spfa

    Trucking 题目连接: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8& ...