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.4 Named Windows

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窗口函数基础初试的主要内容,如果未能解决你的问题,请参考以下文章

MySQL基础--10---MySQL8新特性----窗口函数

将相同的函数绑定到具有不同参数的窗口调整大小事件

Mysql窗口函数

在 MySQL 8 中使用窗口函数获取不同列的计数

初试mysql

mysql存储过程基础