窗口函数 OVER(PARTITION BY ...)

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);

在这里插入图片描述

OVER(PARTITION BY … ORDER BY … DESC)

无分组排序分组排序(对班级)
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,就是最后一名


分组排序函数row_number()、rank() 、dense_rank()、ntile()的区别

  • select ROW_NUMBER()over(order by name) as 排序,* from temp
    — 排序,即使值一样,也不会重复排序。例如1,2,3,4,5
  • select RANK()over(order by name) as 排序,* from temp
    — 排序,值一样,就重复排序,有间隙。例如1,1,3,4
  • select DENSE_RANK()over(order by name) as 排序,* from temp
    — 排序,值一样,就重复排序,没有间隙。例如1,1,2,2,3,4,5
  • select NTILE(2)over(order by name) as 排序,* from temp
    — 排序,分成2组。此函数一般用于取表中前百分之几的数据。例如,取数据的前25%就将数据分4组,然后字段的条件是等于1。

SELECT *, 函数名 OVER(ORDER BY sroce DESC) AS 排序 FROM temp

ROW_NUMBER()      RANK()     DENSE_RANK()     NTILE(2)     

偏移分析窗口函数 lag()、lead()

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 …)

  • exp_str 是字段名称
  • offset 是偏移量, 即是上1个或上N个的值,假设当前行在表中排在第5行,则offset 为3,则表示我们所要找的数据行就是表中的第2行(即5-3=2) 。offset默认值为1。
  • defval 默认值, 当两个函数取上N/下N个值,当在表中从当前行位置向前数N行已经超出了表的范围时,lag()函数将defval这个参数值作为函数的返回值,若没有指定默认值,则返回NUL,那么在数学运算中,总要给一个默认值才不会出错。

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…)

  • A:需要被加工的字段名称
  • B:分组的字段名称
  • C:排序的字段名称
  • D:计算的行数范围

窗口范围说明:

  • preceding:往前
  • following:往后
  • current row:当前行
  • unbounded:起点(一般结合preceding,following使用)
  • unbounded preceding表示该窗口最前面的行(起点)
  • unbounded following:表示该窗口最后面的行(终点)

比如:

  • rows between unbounded preceding and current row - - 表示本行和之前所有的行
  • rows between current row and unbounded following - - 表示本行和之后所有的行
  • rows between 3 preceding and current row - - 表示往前3行到本行(共计4行)
  • rows between 3 preceding and 1 following - - 表示往前3行到往后1行(共计5行)

下面还有很多用法,就不逐一列举了,简单介绍一下,和上面用法类似:
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 …)

  • 25
    点赞
  • 151
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spark SQL中的窗口函数over partition by是一种用于对数据进行分组计算的函数。它可以将数据按照指定的列进行分组,并在每个分组内进行计算。这种函数在数据分析和处理中非常常见,可以帮助我们更方便地进行数据聚合和统计。 ### 回答2: Spark SQL窗口函数是一种强大的函数,可以对窗口内的数据进行分组聚合、排序、排名、分析计算等操作。在实际的数据处理过程中,常常会遇到需要对数据进行分组、聚合等操作的场景,这时候,窗口函数就可以发挥重要作用。 Over partition by是spark sql窗口函数中的一种非常强大的函数,能够对指定字段进行分组聚合。在使用over partition by时,需要定义一个窗口,即用来指定数据的分组方式。通常情况下,partition by子句用来指定需要分组的字段,over子句则用来执行数据计算的操作。 例如,如果需要计算一组数据不同时间点的总和,则可以使用over partition by函数来实现。首先,在select子句中指定需要计算的字段,然后使用over partition子句指定分组方式,最后使用sum函数计算总和。如下所示: ``` SELECT time,value,sum(value) over (partition by time) FROM table_name; ``` 上述示例中,partition by子句使用time字段进行分组,然后将value字段用于计算每个分组的总和。 除了上述示例中的聚合操作,Spark SQL中的over partition by函数还可以执行窗口排序、排名、累计计算、百分比计算等多种计算操作。例如,使用over partition by函数来实现窗口排序,则可以使用排列相关的函数,如rank、dense_rank、row_number等。 总结来说,Spark SQL中的over partition by函数是一种非常强大的窗口函数,可以在数据处理过程中实现复杂的分组、排序、排名、累计计算、百分比计算等多种计算操作。对于需要对数据进行多重分组、聚合分析的场景,使用over partition by函数可以非常方便地实现数据分析处理的任务。 ### 回答3: Spark SQL中的窗口函数over partition by是一种用于在查询结果集中处理数据的功能。窗口函数可以在数据中划分子集,执行聚合函数,计算行号等操作。这些操作与简单的分组聚合或排序不同,因为他们不会对查询结果进行分组,而是对子集进行操作,同时保留查询结果集的完整性。 over partition by语法可用于将查询结果集划分为多个分区,然后在每个分区上执行操作。对于每个分区,分配一个排名或数字,允许在对查询结果集进行其他处理之前,对子集进行排序或聚合操作。 over partition by语法的基本语法格式为: SELECT col1, col2, sum(col3) OVER (PARTITION BY col1) FROM table1 以上语句将查询结果集按照col1进行分区,并对每个分区进行col3的聚合操作,最后在每行返回结果集中的col1、col2、col3聚合总和。 over partition by语法中还可以使用其他聚合函数,如avg()、min()、max()等等。同时,还支持rank()、dense_rank()、row_number()、ntile()等其他更高级的分析函数。 over partition by的使用可以帮助我们更好的处理查询结果集中的数据。通过使用这个功能,我们可以轻松地执行各种分析操作,比如打造数据仪表盘、制定分析计划等等。当我们需要比单个分组细化分析数据时,over partition by语法就是非常有用的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值