赞
踩
MySQL窗口函数,12.21.1 窗口功能说明 https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html
开窗函数的语法结构: 分析函数() over(partition by 分组列名 order by 排序列名 rows between 开始位置 and 结束位置)
over()函数 中包括三个函数:包括分区partition by 列名、排序order by 列名、指定窗口范围rows between 开始位置 and 结束位置
rows between … and … 用得较少,将在最后一节分析
我们知道聚合函数对一组值执行计算并返回单一的值,如sum(),count(),max(),min(), avg()等,这些函数常与group by子句连用。除了 COUNT 以外,聚合函数忽略空值。
但有时候一组数据只返回一组值是不能满足需求的,如我们经常想知道各个地区的前几名、各个班或各个学科的前几名。这时候需要每一组返回多个值。用开窗函数解决这类问题非常方便。它和聚合函数的不同之处是:对于每个组返回多行,而聚合函数对于每个组只返回一行。
DROP TABLE IF EXISTS temp CREATE TABLE temp( id INT, name VARCHAR(10), class VARCHAR(10), score INT ); INSERT INTO temp (id, name, class, score) VALUES (1,'公孙衍', '2', 81); INSERT INTO temp (id, name, class, score) VALUES (2,'廉颇', '3', 55); INSERT INTO temp (id, name, class, score) VALUES (3,'李牧', '3', 55); INSERT INTO temp (id, name, class, score) VALUES (4,'王翦', '1', 96); INSERT INTO temp (id, name, class, score) VALUES (5,'王贲', '1', 92); INSERT INTO temp (id, name, class, score) VALUES (6,'白起', '1', 96); INSERT INTO temp (id, name, class, score) VALUES (7,'蔺相如', '3', 90); INSERT INTO temp (id, name, class, score) VALUES (8,'赵胜', '3', 81); INSERT INTO temp (id, name, class, score) VALUES (9,'赵雍', '3', 93); INSERT INTO temp (id, name, class, score) VALUES (10,'魏无忌', '2', 92);
无分组排序 | 分组排序(对班级) |
---|---|
SELECT name,class,score, ROW_NUMBER() OVER(ORDER BY score DESC) mm FROM temp | SELECT name,class,score, ROW_NUMBER() OVER(PARTITION BY class ORDER BY score DESC) mm FROM temp |
--这个也能实现无分组的排序,只是它没有排序后的次序(也就是没有上面的mm列)
SELECT * FROM temp ORDER BY sroce DESC
实例:
查询每个班的第一名的成绩 | 查询每个班的最后一名的成绩 |
---|---|
SELECT name,class,score FROM (SELECT name,class,score, RANK() OVER(PARTITION BY class ORDER BY score DESC) mm FROM TEMP ) a WHERE mm = 1; | SELECT name,class,score FROM ( SELECT name,class,score, RANK() OVER(PARTITION BY class ORDER BY score) mm FROM temp ) a WHERE mm = 1; |
在求第一名成绩的时候,不能用row_number(),因为如果同班有两个并列第一,mm=1就只返回一个结果
不加desc,排序就默认升序,取mm=1,就是最后一名
SELECT *, 函数名 OVER(ORDER BY sroce DESC) AS 排序 FROM temp
ROW_NUMBER() | RANK() | DENSE_RANK() | NTILE(2) |
---|---|---|---|
lag和lead分析函数可以在同一次查询中,取出同一字段的 前N行的数据(lag)和 后N行的数据(lead)作为独立的列。
在实际应用中,若要用到取今天和昨天的某字段差值时,lag和lead函数的应用就显得尤为重要。当然,这种操作可以用表的自连接实现,但是lag和lead与left join、right join 等自连接相比,效率更高,SQL更简洁。
lag(exp_str, offset, defval) over(partition by … order by …)
lead(exp_str, offset, defval) over(partition by … order by …)
lag() 实例
SELECT id,score,
LAG(score,1,0)OVER() AS n1,
LAG(score,1) OVER() AS n2,
LAG(score,2,0)OVER() AS n6,
LAG(score,2) OVER() AS n7
FROM temp
lead() 实例
SELECT id,score,
LEAD(score,1,0)OVER() AS n1,
LEAD(score,1) OVER() AS n2,
LEAD(score,2,0)OVER() AS n6,
LEAD(score,2) OVER() AS n7
FROM temp
名称 | 描述 |
---|---|
CUME_DIST() | 累计分配值 |
DENSE_RANK() | 当前行在其分区内的排名,没有间隙 |
FIRST_VALUE() | 窗口框架第一行的参数值 |
LAG() | 来自分区内滞后当前行的行的参数值 |
LAST_VALUE() | 窗口框架最后一行的参数值 |
LEAD() | 分区内行前导当前行的参数值 |
NTH_VALUE() | 来自第 N 行窗口框架的参数值 |
NTILE() | 其分区内当前行的桶数 |
PERCENT_RANK() | 百分比排名值 |
RANK() | 当前行在其分区内的排名,有间隙 |
ROW_NUMBER() | 其分区内的当前行数 |
group by是对检索结果的保留行进行单纯分组,一般和聚合函数一起使用例如max、min、sum、avg、count等一块用。 partition by虽然也具有分组功能,但同时也具有其他的高级功能。
sum() over()的使用
显示全部字段是为了方便查看,当有明确目标的时候可以适当选择相应字段。
SELECT t.*, SUM(t.score) s_sum FROM temp t GROUP BY t.class | SELECT t.*, SUM(t.score) OVER(PARTITION BY t.class ORDER BY t.score DESC) s_sum FROM TEMP t | SELECT t.*, SUM(t.score) OVER(ORDER BY t.id) s_sum FROM temp t |
avg() over()的使用
计算移动平均值,一般用于股票变化。
n个数值
{
x
1
,
x
2
,
x
3
,
.
.
.
,
x
n
}
\{ {x_1,x_2,x_3,...,x_n}\}
{x1,x2,x3,...,xn},按顺序取一定个数所做的全部算术平均值。例如
x
1
+
x
2
+
x
3
3
,
x
2
+
x
3
+
x
4
3
,
x
3
+
x
4
+
x
5
3
,
x
4
+
x
5
+
x
6
3
,
.
.
.
.
.
\frac{x_1+x_2+x_3}{3},\frac{x_2+x_3+x_4}{3},\frac{x_3+x_4+x_5}{3},\frac{x_4+x_5+x_6}{3},.....
3x1+x2+x3,3x2+x3+x4,3x3+x4+x5,3x4+x5+x6,..... 等就是移动平均值。
SELECT id, score, AVG(score) OVER(ORDER BY id ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) FROM temp
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
限制计算移动平均值的范围,本语句包含本行和前两行。
语法总结:
avg(…A…) over(partition by …b… order by …C… rows between …D1… and …D2…)
sum(…A…) over(partition by …b… order by …C… rows between …D1… and …D2…)
窗口范围说明:
比如:
下面还有很多用法,就不逐一列举了,简单介绍一下,和上面用法类似:
count() over(partition by … order by …):求分组后的总数。
max() over(partition by … order by …):求分组后的最大值。
min() over(partition by … order by …):求分组后的最小值。
avg() over(partition by … order by …):求分组后的平均值。
lag() over(partition by … order by …):取出前n行数据。
lead() over(partition by … order by …):取出后n行数据。
first_value() over(partition by … order by …):取出第一个数据。
last_value() over(partition by … order by …):取出最后一个数据。
ratio_to_report() over(partition by … order by …):Ratio_to_report() 括号中就是分子,over() 括号中就是分母。
percent_rank() over(partition by … order by …)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。