MySQL窗口函数基础初试
Posted javartisan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL窗口函数基础初试相关的知识,希望对你有一定的参考价值。
mysql支持窗口函数,对于数据row的查询,会使用一些相关的rows进行计算出一个row。如下将会讨论如何使用窗口函数,包括OVER以及WINDOW子句,本结只讨论非聚集窗口函数。聚集窗口函数参考:聚集窗口函数 。更多关于优化以及窗口函数参考:窗口函数优化 。MySQL窗口函数主要涉及一下内容:
12.21.1 Window Function Descriptions
12.21.2 Window Function Concepts and Syntax
12.21.3 Window Function Frame Specification
12.21.5 Window Function Restrictions
MySQL8版本开始支持窗口函数,丰富的一些复杂逻辑的开发,示例代码如下:
show create table open_id_to_pin;
CREATE TABLE `open_id_to_pin`
(
`id` int NOT NULL AUTO_INCREMENT,
`open_id` varchar(32) DEFAULT NULL,
`pin` varchar(32) DEFAULT NULL,
`expire_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
INSERT INTO open_id_to_pin (id, open_id, pin, expire_time) VALUES (1, 'aa', 'a_zs', '2019-01-17 11:31:04');
INSERT INTO open_id_to_pin (id, open_id, pin, expire_time) VALUES (2, 'aa', 'a_ln', '2021-01-17 11:31:28');
INSERT INTO open_id_to_pin (id, open_id, pin, expire_time) VALUES (3, 'bb', 'bb_1', '2021-01-17 11:31:50');
INSERT INTO open_id_to_pin (id, open_id, pin, expire_time) VALUES (4, 'aa', 'a_sd', '2021-01-17 11:31:28');
INSERT INTO open_id_to_pin (id, open_id, pin, expire_time) VALUES (5, 'cc', 'c_sd', '2021-01-17 11:31:28');
INSERT INTO open_id_to_pin (id, open_id, pin, expire_time) VALUES (6, 'cc', 'c_cc', '2021-01-17 11:31:29');
-- CUME_DIST() cume_dist:计算某个值在一组有序的数据中累计的分布
# 计算结果为相对位置/总行数,返回值为(0,1]
# 注意:对于重复值,计算的时候,取重复值的最后一行的位置
select *, CUME_DIST() over (partition by open_id order by expire_time desc )
from open_id_to_pin;
--
-- rank
select *, rank() over (partition by open_id order by expire_time desc )
from open_id_to_pin;
--
select *, dense_rank() over (partition by open_id order by expire_time desc )
from open_id_to_pin;
-- first_value 取分组内排序后,截止到当前行,第一个值
select *, first_value(pin) over (partition by open_id order by expire_time desc )
from open_id_to_pin;
-- LAST_VALUE 取分组内排序后,截止到当前行,最后一个值
select *, last_value(pin) over (partition by open_id order by expire_time desc )
from open_id_to_pin;
-- LAG(col,n,DEFAULT) 用于统计窗口内往上第n行值 第一个参数为列名,第二个参数为往上第n行(可选,默认为1),第三个参数为默认值(当往上第n行为NULL时候,取默认值,如不指定,则为NULL)
select *, lag(pin, 1, null) over (partition by open_id order by expire_time )
from open_id_to_pin;
-- LEAD 与LAG相反 LEAD(col,n,DEFAULT) 用于统计窗口内往下第n行值 第一个参数为列名,第二个参数为往下第n行(可选,默认为1),第三个参数为默认值(当往下第n行为NULL时候,取默认值,如不指定,则为NULL)
select *, lead(pin, 1, null) over (partition by open_id order by expire_time)
from open_id_to_pin;
-- NTH_VALUE() 返回窗口的第N行
select *, NTH_VALUE(pin, 2) over (partition by open_id order by expire_time desc)
from open_id_to_pin;
-- NTILE 划分分组,将窗口内部的划分为N组,也可以叫做N个bucket
select *, NTILE(3) over (partition by open_id order by expire_time desc)
from open_id_to_pin;
-- percent_rank计算逻辑:(rank - 1) / (rows - 1)
# 计算方法为(相对位置-1)/(总行数-1)
# 注意:对于重复值,计算的时候,取重复值的第一行的位
select *, percent_rank() over (partition by open_id order by expire_time desc)
from open_id_to_pin;
-- 对于窗口生成临时表的写法
select *, rank() over w
from open_id_to_pin
window w as (partition by open_id order by expire_time desc );
# 计算行号
SELECT @rownum := @rownum + 1 AS rownum,
e.*
FROM (SELECT @rownum := 0) r,
open_id_to_pin e;
#相关子查询
select *
from open_id_to_pin a
where a.expire_time in (select max(b.expire_time) from open_id_to_pin b where a.open_id = b.open_id)
# 窗口函数实现openid相同取最新的记录
select *
from (select *, row_number() over (partition by open_id order by expire_time desc ) as rn
from open_id_to_pin
) tab
where tab.rn = 1;
# ---------------------------------
# 相同点:RANK()和DENSE_RANK()的是排名函数
# 不同点:RANK()是跳跃排序,即如果有两条记录重复,接下来是第三级别
# 如:1 2 2 4,会跳过3
# DENSE_RANK()是连续排序,即如果有两条记录重复,接下来是第二级别
# 如:1 2 2 3
# 按照open_id划分窗口以及按照 exipre_time 排序
select *, rank() over (partition by open_id order by expire_time desc) as rk
from open_id_to_pin;
select *, dense_rank() over (partition by open_id order by expire_time desc) as rk
from open_id_to_pin;
# 按照open_id划分窗口以及按照open_id排序
select *, rank() over (partition by open_id order by open_id desc) as rk
from open_id_to_pin;
select *, dense_rank() over (partition by open_id order by open_id desc) as rk
from open_id_to_pin;
官方参考:https://dev.mysql.com/doc/refman/8.0/en/window-functions.html
以上是关于MySQL窗口函数基础初试的主要内容,如果未能解决你的问题,请参考以下文章