MySQL被Orcale收购了之后,MySQL8.0继承了Orcale的窗口函数(又称:开窗函数),这个功能在大多商业数据库如Orcale和PostgreSQL中早已支持。
MySQL的窗口函数也称为OLAP函数,OLAP是Online Analytical Processing的简称,意思是对数据库进行实时分析处理,也叫分析函数。
create table order_tab(
order_id int,
user_no varchar(3),
amount int,
create_date date
);
insert into order_tab values
(1,'001',100,'2019-01-01'),
(2,'001',300,'2019-01-02'),
(3,'001',500,'2019-01-02'),
(4,'001',800,'2019-01-03'),
(5,'001',900,'2019-01-04'),
(6,'002',500,'2019-01-03'),
(7,'002',600,'2019-01-04'),
(8,'002',300,'2019-01-10'),
(9,'002',800,'2019-01-16'),
(10,'002',800,'2019-01-22');
select * from order_tab;
select *,sum(amount)over(partition by user_no) from order_tab;
函数 | 描述 |
---|---|
cume_dist() | 计算一组值中一个值的累计分布 |
dense_rank() | 根据该order by 子句为分区中的每一行分配一个排名。它将相同的排名分配给具有相等值的行。如果两行或者更多行具有相同的排名,则排名值序列中将没有间隙。 |
rank() | 与dense_rank() 函数相似,不同之处在于当两行或更多行具有相同的排名时,排名值序列中存在间隙。 |
row_number() | 为分区中的每一行分配一个顺序整数排名 |
first_value | 返回相对于窗口框架第一行的指定表达式的值。 |
log() | 返回分区中当前行之前的第N行的值。如果不存在前一行,则返回NULL |
last_value() | 返回对于窗口框架中最后一行的指定表达式的值。 |
lead() | 返回分区中当前行之后的第N行的值。如果不存在后续行,则返回NULL。 |
nth_value() | 从窗口框架的第N行返回参数的值。 |
ntle() | 将每个窗口分区的行分配到指定数量的排名组中。 |
percent_rank() | 计算分区或结果集中行的百分数排名。 |
开窗函数名([<字段名>]) over([partition by <分组字段>] [order by <排序字段> [desc]] [<窗口分区>])
partition by
子句配合使用,也可以单独使用。SELECT
*
FROM
(
SELECT
*, row_number () over (
PARTITION BY user_no
ORDER BY
amount DESC
) max_amount
FROM
order_tab
) t
WHERE
t.max_amount <= 3
通过使用row_number()
函数对分组后的订单金额进行倒序排序,取前三个即可。
SELECT
*, row_number () over (
PARTITION BY user_no
ORDER BY
amount DESC
) rank1,
rank () over (
PARTITION BY user_no
ORDER BY
amount DESC
) rank2,
dense_rank () over (
PARTITION BY user_no
ORDER BY
amount DESC
) rank3
FROM
order_tab
可以直观的看出三种排序函数的区别。
percent_rank():
: 分组内小于当前rank值的行数 / 分组内除当前rank值所在记录外的行数,计算方法:(当前rank - 1)/ (rows - 1)
其中,rank是rank()函数产生的序号,rows是窗口的记录总行数。
SELECT
*, rank () over (
PARTITION BY user_no
ORDER BY
amount
) rank1,
percent_rank () over (
PARTITION BY user_no
ORDER BY
amount
) percent_rank1
FROM
order_tab
cume_dist()
: 分组内小于等于当前rank值的行数 / 分组内总行数,计算方法: rank / rows
SELECT
*, rank () over (
PARTITION BY user_no
ORDER BY
amount DESC
) rank1,
cume_dist () over (
PARTITION BY user_no
ORDER BY
amount DESC
) cume1
FROM
order_tab
lag(n,m)
: 分区内(当前行n)往前数的第m行。
lead(n,m)
:分区内(当前行n)往后数第m行。
date_diff(n,m)
:计算两个日期之间的天数。
SELECT
*, datediff(create_date, last_date)
FROM
(
SELECT
*, lag (create_date, 1) over (
PARTITION BY user_no
ORDER BY
create_date
) last_date
FROM
order_tab
) d
first_value()
:分区中的第一个值
last_value()
:分区中的根据排序参数的最后一个值
SELECT
*, first_value (amount) over (
PARTITION BY user_no
ORDER BY
create_date
) value1,
last_value (amount) over (
PARTITION BY user_no
ORDER BY
create_date
) value2
FROM
order_tab
nth_value(expr,n)
: 返回分组中第N个expr的值,expr可以是表达式,也可以是列名。
SELECT
*, nth_value (amount, 2) over (
PARTITION BY user_no
ORDER BY
amount
) secoud_amount,
nth_value (amount, 3) over (
PARTITION BY user_no
ORDER BY
amount
) third_amount
FROM
order_tab
ntile(expr)
: 函数将有序数据集划分为 expr 指示的若干桶,并为每一行分配适当的桶号。
SELECT
*, ntile (3) over (
PARTITION BY user_no
ORDER BY
create_date
)
FROM
order_tab
MySQL8.0官网文档:https://dev.mysql.com/doc/refman/8.0/en/window-functions-usage.html
=========================================================
人生得意须尽欢,莫使金樽空对月!
__一个热爱说唱的程序员。
=========================================================