Row_Number() over( PARTITION By cno ...)
转自:https://blog.csdn.net/qq_25237107/article/details/64442969
1.在 MSSQL,oracle 有partition by 的用法
create table score
(
sno varchar(20) ,
cno varchar(20),
degree int
) insert into score (sno ,cno ,degree ) values ('001','a',100)
insert into score (sno ,cno ,degree ) values ('002','a',99)
insert into score (sno ,cno ,degree ) values ('003','a',98)
insert into score (sno ,cno ,degree ) values ('004','a',97)
insert into score (sno ,cno ,degree ) values ('001','b',100)
insert into score (sno ,cno ,degree ) values ('002','b',100)
insert into score (sno ,cno ,degree ) values ('003','b',99)
insert into score (sno ,cno ,degree ) values ('004','b',98)
insert into score (sno ,cno ,degree ) values ('001','c',100)
insert into score (sno ,cno ,degree ) values ('002','c',100)
insert into score (sno ,cno ,degree ) values ('003','c',99)
insert into score (sno ,cno ,degree ) values ('004','c',98) select * from
(
select *,ROW_NUMBER () over(PARTITION BY cno order by degree desc) as pm from score
) x
where x.pm <=3 select * from
(
select *,rank () over(PARTITION BY cno order by degree desc) as pm from score
) x
where x.pm <=3 select * from
(
select *,dense_rank () over(PARTITION BY cno order by degree desc) as pm from score
) x
where x.pm <=3 2.在 mysql中 没有 ROW_NUMBER()over(partition by ... order by ...) 这种写法
需要用其他 替代方法:
方法一:
DROP TABLE IF EXISTS `score`;
CREATE TABLE `score` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`subject_id` char(10) DEFAULT NULL,
`student_id` char(10) DEFAULT NULL,
`score` float DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8;
INSERT INTO score
select NULL,'1','001',100
UNION
SELECT NULL,'1','002',90
UNION
SELECT null,'1','003',80
UNION
select null,'1','004',99
UNION
select null,'1','005',78
UNION
select null,'1','006',89
UNION
select NULL,'1','001',100
UNION
SELECT NULL,'1','002',90
UNION
SELECT null,'1','003',80
UNION
select null,'1','004',99
UNION
select null,'1','005',78
UNION
select null,'1','006',89
2.
相当于自身全连接:
SELECT AA.*,BB.* FROM score AA JOIN score BB
on AA.subject_id=BB.subject_id AND AA.score>=BB.score
ORDER BY AA.subject_id,AA.score DESC
3. group by 之
SELECT AA.*,BB.* FROM score AA JOIN score BB
on AA.subject_id=BB.subject_id AND AA.score>=BB.score
GROUP BY AA.student_id,AA.subject_id,AA.score
ORDER BY AA.subject_id,AA.score DESC
4.having 之
SELECT AA.id,AA.student_id,AA.subject_id,AA.score FROM score AA JOIN score BB
on AA.subject_id=BB.subject_id AND AA.score>=BB.score
GROUP BY AA.student_id,AA.subject_id,AA.score
HAVING count(AA.subject_id)>=4
ORDER BY AA.subject_id,AA.score DESC
注意: mysql 与 MSsql 之 group by 是不相同的
mysql 使用 group by 后 select 可以 全部字段. mssql 是不行的
方法二:
Mysql 分组聚合实现 over partition by 功能
转自:https://www.cnblogs.com/zhwbqd/p/4205821.html
https://blog.csdn.net/zzm628/article/details/52181382
mysql中没有类似oracle和postgreSQL的 OVER(PARTITION BY)功能. 那么如何在MYSQL中搞定分组聚合的查询呢
先说结论: 利用 group_concat + substr等函数处理
例如: 订单表一张, 只保留关键字段
id | user_id | money | create_time |
1 | 1 | 50 | 1420520000 |
2 | 1 | 100 | 1420520010 |
3 | 2 | 100 | 1420520020 |
4 | 2 | 200 | 1420520030 |
业务: 查找每个用户的最近一笔消费金额
单纯使用group by user_id, 只能按user_id 将money进行聚合, 是无法将最近一单的金额筛选出来的, 只能满足这些需求, 例如: 每个用户的总消费金额 sum(money), 最大消费金额 max(money), 消费次数count(1) 等
但是我们有一个group_concat可以用, 思路如下:
1. 查找出符合条件的记录, 按user_id asc, create_time desc 排序;
select ord.user_id, ord.money, ord.create_time from orders ord where ord.user_id > 0 and create_time > 0 order by ord.user_id asc , ord.create_time desc
user_id | money | create_time |
1 | 100 | 1420520010 |
1 | 50 | 1420520000 |
2 | 200 | 1420520030 |
2 | 100 | 1420520020 |
2. 将(1)中记录按user_id分组, group_concat(money);
select t.user_id, group_concat( t.money order by t.create_time desc ) moneys from (select ord.user_id, ord.money, ord.create_time from orders ord where ord.user_id > 0 and ord.create_time > 0 order by ord.user_id asc , ord.create_time desc) t group by t.user_id
user_id | moneys |
1 | 100,50 |
2 | 200,100 |
3. 这时, 如果用户有多个消费记录, 就会按照时间顺序排列好, 再利用 subString_index 函数进行切分即可
完整SQL, 注意group_concat的内排序, 否则顺序不保证, 拿到的就不一定是第一个了
select t.user_id, substring_index(group_concat( t.money order by t.create_time desc ),',',1) lastest_money from (select ord.user_id, ord.money, ord.create_time from orders ord where ord.user_id > 0 and create_time > 0 order by user_id asc , create_time desc) t group by user_id ;
user_id | moneys |
1 | 100 |
2 | 200 |
利用这个方案, 以下类似业务需求都可以这么做, 如:
1. 查找每个用户过去10个的登陆IP
2. 查找每个班级中总分最高的两个人
补充: 如果是只找出一行记录, 则可以直接只用聚合函数来进行
select t.user_id, t.money from (select ord.user_id, ord.money, ord.create_time from orders ord where ord.user_id > 0 and create_time > 0 order by user_id asc , create_time desc) t group by user_id ;
前提一定是(1) 只需要一行数据, (2) 子查询中已排好序, (3) mysql关闭 strict-mode
参考资料:
http://dev.mysql.com/doc/refman/5.0/en/sql-mode.html#sql-mode-strict
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat
有任何问题请不吝赐教, 谢谢!
Row_Number() over( PARTITION By cno ...)的更多相关文章
- sql 分组取最新的数据sqlserver巧用row_number和partition by分组取top数据
SQL Server 2005后之后,引入了row_number()函数,row_number()函数的分组排序功能使这种操作变得非常简单 分组取TOP数据是T-SQL中的常用查询, 如学生信息管理系 ...
- ROW_NUMBER()与PARTITION BY 实例
环境:SQL Server 2008 R2 数据表结构 SELECT A.* FROM [tbiz_AssScoreWeidu] A SELECT A.* ,ROW_NUMBER() OVER ( P ...
- row_number和partition by分组取top数据
分组取TOP数据是T-SQL中的常用查询, 如学生信息管理系统中取出每个学科前3名的学生.这种查询在SQL Server 2005之前,写起来很繁琐,需要用到临时表关联查询才能取到.SQL Serve ...
- 去重 ROW_NUMBER() OVER(PARTITION BY 分组字段 ORDER BY 排序字段) RN
关键字 ROW_NUMBER() OVER(PARTITION BY 分组字段 ORDER BY 排序字段) RN 按照分组字段进行排序并标编号 ROW_NUMBER() OVER(PARTITIO ...
- row_number()over(partition by 字段 order by 字段)ID,修改重复行的字段值。
案例分析: 现在要查询一个表单里面的运费结果,但是他还有分录,为了显示分录,必须把表头显示出来,问题是,他要查询运费的合计, 但是这样就会导致重复行也加进去了,这样显然数据不准,为此,可以把重复的行设 ...
- row_number() OVER(PARTITION BY)函数介绍
OVER(PARTITION BY)函数介绍 开窗函数 Oracle从8.1.6开始提供分析函数,分析函数用于计算基于组的某种聚合值,它和聚合函数的不同之处是:对于每个 ...
- sqlserver巧用row_number和partition by分组取top数据
SELECT * FROM( SELECT orderid,createtime, ROW_NUMBER() over(PARTITION by orderid order by createtime ...
- SQL技术内幕-4 row_number() over( partition by XX order by XX)的用法(区别于group by 和order by)
partition by关键字是分析性函数的一部分,它和聚合函数不同的地方在于它能返回一个分组中的多条记录,而聚合函数一般只有一条反映统计值的记录,partition by用于给结果集分组,如果没有指 ...
- row_number() OVER (PARTITION BY COL1 ORDER BY COL2)
select *,ROW_NUMBER() over(partition by deviceID order by RecordDate desc row_number() OVER (PARTITI ...
随机推荐
- pandas_datareader.data 和 fix_yahoo_finance 获取金融数据
参考:https://zhuanlan.zhihu.com/p/35360694 1.获取数据 #定义所需要的数据 gafataDict={"谷歌":"GOOG" ...
- Loki之Funtion
阅读Loki中Funtion源码之后的个人理解,该库归纳起来可以说有三层(C++设计新思维列举到2个参数,此处列举到3个参数),要记住C++的模板其实就是C语言高级的宏定义,如果用户没有用到对应的模板 ...
- Using virtual lists
Download demo project - 15.7 Kb Contents Introduction Virtual list Creating a virtual list Add items ...
- LayoutInflater的动态增加控件
在实际开发中LayoutInflater这个类是非常有用的,它的作用类似于 findViewById(),不同点是LayoutInflater是用来找layout下xml布局文件. 而findView ...
- 【IPC进程间通讯之中的一个】邮槽MailSlot
IPC进程间通信+邮槽MailSlot IPC(Inter-Process Communication.进程间通信). 现代计算机採用虚拟内存机制,为进程提 ...
- 使用Spring注解获取配置文件信息
需要加载的配置文件内容(resource.properties): #FTP相关配置 #FTP的IP地址 FTP_ADDRESS=192.168.1.121 FTP_PORT=21 FTP_USERN ...
- libevent基础知识
在线手册 • 官方网站:http://libevent.org/ • 官方手册:http://www.wangafu.net/~nickm/libevent-book/ • 官方下载:http://s ...
- (转)VS中的路径宏 vc++中OutDir、ProjectDir、SolutionDir各种路径说明
$(RemoteMachine) 设置为“调试”属性页上“远程计算机”属性的值.有关更多信息,请参见更改用于 C/C++ 调试配置的项目设置. $(References) 以分号分隔的引用列表被添 ...
- POI 导出文件 报空指针异常 --Docker 中
应用导出文件时 报空指针异常 莫名的地方Docker 使用的是轻量级的 jdk 需要更换 jdkDockerfile 中修改配置- registry-docker.zhaopin.com.cn/too ...
- deeplenrnig学习笔记——什么是特征
特征是机器学习系统的原材料,对最终模型的影响是毋庸置疑的.如果数据被很好的表达成了特征,通常线性模型就能达到满意的精度. 一.特征的表示粒度: 学习算法在一个什么粒度上的特征表示,才有能发挥作用 ...