mysql实现开窗函数

mysql实现开窗函数#

开窗分析函数简单来说就是类似partition by aaa, bbb order by ccc这样的形式

在使用mysql的过程中遇到过这样的需求,需要求出一段时间内每个item的最大值及对应的那一条记录。最大值很容易使用group by item求出来,但是求出那一条对应的所有字段及值却不好实现。经过查资料及探索发现mysql也可以实现,思路是人为构造一个字段来标记顺序,这样不仅能实现最大,还能实现TOP N。记录下简单示例:

准备数据#

Copy
# 建表 CREATE TABLE `policy_summary` ( `id` int(11) NOT NULL AUTO_INCREMENT, `policy_name` varchar(18) COLLATE utf8_bin DEFAULT NULL, `publish_time` datetime DEFAULT NULL, `platform_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) # 插入数据 INSERT INTO `policy_summary` VALUES ('1', 'test0', '2019-04-01 15:11:00', '2'); INSERT INTO `policy_summary` VALUES ('2', 'test9', '2019-04-01 19:11:00', '2'); INSERT INTO `policy_summary` VALUES ('3', 'test8', '2019-04-01 19:11:00', '2'); INSERT INTO `policy_summary` VALUES ('4', 'test7', '2019-04-01 18:11:00', '2'); INSERT INTO `policy_summary` VALUES ('5', 'test1', '2019-04-01 15:11:00', '2'); INSERT INTO `policy_summary` VALUES ('6', 'test2', '2019-04-01 15:11:00', '2'); INSERT INTO `policy_summary` VALUES ('7', 'test3', '2019-04-01 16:11:00', '2'); INSERT INTO `policy_summary` VALUES ('8', 'test4', '2019-04-01 16:11:00', '2'); INSERT INTO `policy_summary` VALUES ('9', 'test5', '2019-04-01 16:11:00', '2'); INSERT INTO `policy_summary` VALUES ('10', 'test6', '2019-04-01 17:11:00', '2'); INSERT INTO `policy_summary` VALUES ('11', 'fengyu', '2019-04-02 19:17:00', '8'); INSERT INTO `policy_summary` VALUES ('12', '新建政策1111111', '2019-04-02 19:17:00', '8'); INSERT INTO `policy_summary` VALUES ('13', '1218测试', '2019-04-02 19:17:00', '8'); INSERT INTO `policy_summary` VALUES ('14', 'xxx', '2019-04-02 19:17:00', '8'); INSERT INTO `policy_summary` VALUES ('15', 'ccc', '2019-04-02 19:17:00', '8'); INSERT INTO `policy_summary` VALUES ('16', '测试114', '2019-04-02 19:17:00', '8'); INSERT INTO `policy_summary` VALUES ('17', '测试mmm', '2019-04-02 19:17:00', '8'); INSERT INTO `policy_summary` VALUES ('18', 'kkkkkkk', '2019-04-02 19:17:00', '8'); INSERT INTO `policy_summary` VALUES ('19', 'kkkkkkk明明', '2019-04-02 19:17:00', '8'); INSERT INTO `policy_summary` VALUES ('20', 'ceshi111', '2019-04-02 19:17:00', '8'); # 查看 mysql> select * from policy_summary; +----+-----------------+---------------------+-------------+ | id | policy_name | publish_time | platform_id | +----+-----------------+---------------------+-------------+ | 1 | test0 | 2019-04-01 15:11:00 | 2 | | 2 | test9 | 2019-04-01 19:11:00 | 2 | | 3 | test8 | 2019-04-01 19:11:00 | 2 | | 4 | test7 | 2019-04-01 18:11:00 | 2 | | 5 | test1 | 2019-04-01 15:11:00 | 2 | | 6 | test2 | 2019-04-01 15:11:00 | 2 | | 7 | test3 | 2019-04-01 16:11:00 | 2 | | 8 | test4 | 2019-04-01 16:11:00 | 2 | | 9 | test5 | 2019-04-01 16:11:00 | 2 | | 10 | test6 | 2019-04-01 17:11:00 | 2 | | 11 | fengyu | 2019-04-02 19:17:00 | 8 | | 12 | 新建政策1111111 | 2019-04-02 19:17:00 | 8 | | 13 | 1218测试 | 2019-04-02 19:17:00 | 8 | | 14 | xxx | 2019-04-02 19:17:00 | 8 | | 15 | ccc | 2019-04-02 19:17:00 | 8 | | 16 | 测试114 | 2019-04-02 19:17:00 | 8 | | 17 | 测试mmm | 2019-04-02 19:17:00 | 8 | | 18 | kkkkkkk | 2019-04-02 19:17:00 | 8 | | 19 | kkkkkkk明明 | 2019-04-02 19:17:00 | 8 | | 20 | ceshi111 | 2019-04-02 19:17:00 | 8 | +----+-----------------+---------------------+-------------+

根据platform_id,publish_time分组并根据policy_name排序#

Copy
SELECT a.platform_id, a.publish_time, a.policy_name, a.id, IF ( @str1 = a.platform_id AND @str2 = a.publish_time, @rank := @rank + 1, @rank := 1 ) AS rank_no, @str1 := a.platform_id, @str2 := a.publish_time FROM ( SELECT platform_id, publish_time, policy_name, id FROM policy_summary ORDER BY platform_id, publish_time, policy_name ASC ) a, ( SELECT @str1 := 0, @str2 := NULL, @rank := 0 ) tmp # 查询结果 +-------------+---------------------+-----------------+----+---------+------------------------+-------------------------+ | platform_id | publish_time | policy_name | id | rank_no | @str1 := a.platform_id | @str2 := a.publish_time | +-------------+---------------------+-----------------+----+---------+------------------------+-------------------------+ | 2 | 2019-04-01 15:11:00 | test0 | 1 | 1 | 2 | 2019-04-01 15:11:00 | | 2 | 2019-04-01 15:11:00 | test1 | 5 | 2 | 2 | 2019-04-01 15:11:00 | | 2 | 2019-04-01 15:11:00 | test2 | 6 | 3 | 2 | 2019-04-01 15:11:00 | | 2 | 2019-04-01 16:11:00 | test3 | 7 | 1 | 2 | 2019-04-01 16:11:00 | | 2 | 2019-04-01 16:11:00 | test4 | 8 | 2 | 2 | 2019-04-01 16:11:00 | | 2 | 2019-04-01 16:11:00 | test5 | 9 | 3 | 2 | 2019-04-01 16:11:00 | | 2 | 2019-04-01 17:11:00 | test6 | 10 | 1 | 2 | 2019-04-01 17:11:00 | | 2 | 2019-04-01 18:11:00 | test7 | 4 | 1 | 2 | 2019-04-01 18:11:00 | | 2 | 2019-04-01 19:11:00 | test8 | 3 | 1 | 2 | 2019-04-01 19:11:00 | | 2 | 2019-04-01 19:11:00 | test9 | 2 | 2 | 2 | 2019-04-01 19:11:00 | | 8 | 2019-04-02 19:17:00 | 1218测试 | 13 | 1 | 8 | 2019-04-02 19:17:00 | | 8 | 2019-04-02 19:17:00 | ccc | 15 | 2 | 8 | 2019-04-02 19:17:00 | | 8 | 2019-04-02 19:17:00 | ceshi111 | 20 | 3 | 8 | 2019-04-02 19:17:00 | | 8 | 2019-04-02 19:17:00 | fengyu | 11 | 4 | 8 | 2019-04-02 19:17:00 | | 8 | 2019-04-02 19:17:00 | kkkkkkk | 18 | 5 | 8 | 2019-04-02 19:17:00 | | 8 | 2019-04-02 19:17:00 | kkkkkkk明明 | 19 | 6 | 8 | 2019-04-02 19:17:00 | | 8 | 2019-04-02 19:17:00 | xxx | 14 | 7 | 8 | 2019-04-02 19:17:00 | | 8 | 2019-04-02 19:17:00 | 新建政策1111111 | 12 | 8 | 8 | 2019-04-02 19:17:00 | | 8 | 2019-04-02 19:17:00 | 测试114 | 16 | 9 | 8 | 2019-04-02 19:17:00 | | 8 | 2019-04-02 19:17:00 | 测试mmm | 17 | 10 | 8 | 2019-04-02 19:17:00 | +-------------+---------------------+-----------------+----+---------+------------------------+-------------------------+

这样rank_no就是那个标志排序的字段,如果要求最大policy_name的记录就只需要加一个过滤条件rank_no <= 1即可

Copy
SELECT t.platform_id, t.publish_time, t.policy_name, t.rank_no, t.id FROM ( SELECT a.id, a.platform_id, a.publish_time, a.policy_name, IF ( @str1 = a.platform_id AND @str2 = a.publish_time, @rank := @rank + 1, @rank := 1 ) AS rank_no, @str1 := a.platform_id, @str2 := a.publish_time FROM ( SELECT id, platform_id, publish_time, policy_name FROM policy_summary ORDER BY platform_id, publish_time, policy_name ASC ) a, ( SELECT @str1 := 0, @str2 := NULL, @rank := 0 ) tmp ) t WHERE t.rank_no <= 1

参考#

https://www.jianshu.com/p/2e8a29d3d669

posted @   村口王铁匠  阅读(1018)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示

目录

目录

×