mysql8 的window function 解决分组后多行取某一行的完整数据(ONLY_FULL_GROUP_BY模式下)

本文介绍了如何利用MySQL8的窗口函数在ONLY_FULL_GROUP_BY模式下,解决分组查询时获取每个分组内特定行的完整数据。通过创建窗口并按条件排序,结合ROW_NUMBER()函数,可以有效地选取每组的最大值或其他所需行。示例中展示了针对total最大值的选择,并演示了如何在有多个最大值时,通过额外条件(如other字段)进一步筛选。
摘要由CSDN通过智能技术生成

mysql8window function 解决分组后多行取某一行的完整数据(ONLY_FULL_GROUP_BY模式下)

注:非ONLY_FULL_GROUP_BY模式的就不再赘述!
参考https://dev.mysql.com/doc/refman/8.0/en/window-functions.html

表结构

CREATE TABLE `aa` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `total` int(11) NOT NULL,
  `code` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `other` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC;

数据

INSERT INTO `aa` VALUES (1, 10, '001', 'aaaa');
INSERT INTO `aa` VALUES (2, 20, '003', 'bbbb');
INSERT INTO `aa` VALUES (3, 30, '002', 'cccc');
INSERT INTO `aa` VALUES (4, 40, '002', 'dddd');
INSERT INTO `aa` VALUES (5, 40, '002', 'eeee');
INSERT INTO `aa` VALUES (6, 25, '002', 'ffff');
INSERT INTO `aa` VALUES (7, 5, '001', 'gggg');
INSERT INTO `aa` VALUES (8, 35, '003', 'hhhh');

在这里插入图片描述

需求:获取每种code下的total最大值坐在的整行数据 即

在这里插入图片描述

注:这里可以看出来 id45的数据都是total都是40code都是002,这里还可以按照other排序来获取结果显示id4的还是5的数据(下面会体现)

先不用窗口函数(window function)想一下思路:

先根据code分组,再取最大的total,但是发现code002的数据有两条最大的都是40mysql会选择哪条的other字段呢?
ONLY_FULL_GROUP_BY模式 是取不到other的,如果再join这张表,code=code and total = total 那也会出现两条
在这里插入图片描述
还是很难筛选,所以不采用这种办法!

好在mysql8.0提供了类似于oracle数据库的窗口函数

来看下window function的实现,甚至都不需要group by

先根据codePARTITION) 分区(和mysql里的分区表没有任何关系,更像是分组)
再分区之后对total字段进行order by 降序
row_number() 体现分区内的行数,递增

SELECT
	id,
	total,
	other,
	CODE,
	ROW_NUMBER() over ( PARTITION BY CODE ORDER BY total DESC, other DESC ) AS rn 
FROM
	aa

或者 定义一个带namewindow , name"w" ,方便重复使用

SELECT
	id,
	total,
	other,
	CODE,
	ROW_NUMBER() over w AS rn 
FROM
	aa window w AS ( PARTITION BY CODE ORDER BY total DESC )) AS t

得到的结果如下
在这里插入图片描述
可以看出来 同一个code下最大的total 所对应的rn都是1

那只需要对这个临时表进行查询,条件为rn = 1 就可以得到所需要的数据了

SELECT
	* 
FROM
	(
	SELECT
		id,
		total,
		other,
		CODE,
		ROW_NUMBER() over w AS rn 
	FROM
	aa window w AS ( PARTITION BY CODE ORDER BY total DESC )) AS t 
WHERE
	rn = 1

在这里插入图片描述
以上完成了需求的功能。

可以看出上图标红线的id4的数据,还记得id5 的数据也是code002但是othereeee,那我现在想要otherdddd的怎么办?(id4id5 区别在于other字段一个为dddd一个为eeee
好办,只需要在分区里面加上对other加上排序
在这里插入图片描述
可以看出顺序已经变了,在查询一下这个临时表
在这里插入图片描述
结果正确

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值