窗口函数的实现

本文介绍了如何在MySQL8.0版本之前通过嵌套子查询的方式模拟窗口函数功能,处理时间序列数据并按id和时间分组,给出了两种实现方法:一是基于行号的计数,二是多维度分组计数。
摘要由CSDN通过智能技术生成

窗口函数的实现

简介

窗口函数的实现 & MySQL 实现窗口函数功能
众所周知: MySQL从8.0版本开始支持窗口函数, 但是对于8.0版本之前的MySQL是无法使用窗口函数的, 我们可以通过一个类似嵌套子查询的方式, 来实现窗口函数的功能 ;

1. 问题
使用sql完成,且不能使用窗口函数
由数据A如下: 
id	time	name
1001	'2023-11-06'	a
1001	'2023-11-10'	a
1001	'2023-11-23'	b
1001	'2023-12-08'	b
1001	'2023-12-11'	a
1001	'2023-12-28'	a

得到数据B如下: 
id	mame	min_date	max_date
1001	a	'2023-11-06'	'2023-11-10'
1001	b	'2023-11-23'	'2023-12-08'
1001	a	'2023-12-11'	'2023-12-28'

注意: 时间中间有穿插的, 分开统计
2. 解决方法
-- 方法一: 使用窗口函数
WITH t_1 AS (
SELECT * FROM (
VALUES  
 (1001,	'2023-11-06',	'a')
,(1001,	'2023-11-10',	'a')
,(1001,	'2023-11-23',	'b')
,(1001,	'2023-12-08',	'b')
,(1001,	'2023-12-11',	'a')
,(1001,	'2023-12-28',	'a')
) AS table_name(id, time, name) 
)

SELECT id, name, MIN(time) AS min_date, MAX(time) AS max_date
FROM (
    SELECT id, name, time, 
           ROW_NUMBER() OVER (PARTITION BY id ORDER BY time) -
           ROW_NUMBER() OVER (PARTITION BY id, name ORDER BY time) AS grp
    FROM t_1
) AS temp
GROUP BY id, name, grp;
idnamemin_datemax_date
1001a2023-11-062023-11-10
1001a2023-12-112023-12-28
1001b2023-11-232023-12-08
-- 方法二: 实现窗口函数
WITH A AS (
SELECT * FROM (
VALUES  
 (1001,	'2023-11-06',	'a')
,(1001,	'2023-11-10',	'a')
,(1001,	'2023-11-23',	'b')
,(1001,	'2023-12-08',	'b')
,(1001,	'2023-12-11',	'a')
,(1001,	'2023-12-28',	'a')
) AS table_name(id, time, name) 
)

SELECT 
    id, name, MIN(time) AS min_date, MAX(time) AS max_date
FROM (
    SELECT
        id, name, time
        , (SELECT COUNT(*) FROM A AS A2 WHERE A2.id = A1.id AND A2.time <= A1.time ) 
        - (SELECT COUNT(*) FROM A AS A3 WHERE A3.id = A1.id AND A3.name = A1.name AND A3.time <= A1.time) AS rn
      FROM A AS A1
) t1
GROUP BY id, name, rn
;
idnamemin_datemax_date
1001a2023-11-062023-11-10
1001a2023-12-112023-12-28
1001b2023-11-232023-12-08
总结:
-- 利用 id 和 时间的关系, 统计每个id和时间到目前为止 id出现次数, 实现 对次id根据时间顺序进行排序的功能
(SELECT COUNT(*) FROM A AS A2 WHERE A2.id = A1.id AND A2.time <= A1.time ) 
-->
ROW_NUMBER() OVER (PARTITION BY id ORDER BY time)

-- 同理: 多维度分组的数据, 就对维度进行管理, 对排序数据进行比较
(SELECT COUNT(*) FROM A AS A3 WHERE A3.id = A1.id AND A3.name = A1.name AND A3.time <= A1.time)
ROW_NUMBER() OVER (PARTITION BY id, name ORDER BY time)
end
  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值