抖音资讯

douyinzx

sql开窗函数有哪些(sql窗口函数和开窗函数讲解)

iseeyu2年前 (2024-05-06)抖音资讯151

1.概述

介绍

相信用过MySQL的朋友都知道,MySQL中也有开窗函数的存在。开窗函数的引入是为了既显示聚集前的数据,又显示聚集后的数据。即在每一行的最后一列添加聚合函数的结果。

 

开窗用于为行定义一个窗口(这里的窗口是指运算将要操作的行的集合),它对一组值进行操作,不需要使用 GROUP BY 子句对数据进行分组,能够在同一行中同时返回基础行的列和聚合列。

 

聚合函数和开窗函数

聚合函数是将多行变成一行,count,avg…

开窗函数是将一行变成多行

聚合函数如果要显示其他的列必须将列加入到group by中

开窗函数可以不使用group by,直接将所有信息显示出来

 

开窗函数分类

聚合开窗函数

聚合函数(列) OVER(选项),这里的选项可以是PARTITION BY 子句,但不可以是 ORDER BY 子句。

 

排序开窗函数

排序函数(列) OVER(选项),这里的选项可以是ORDER BY 子句,也可以是OVER(PARTITION BY 子句 ORDER BY 子句),但不可以是 PARTITION BY 子句。

 

2. 准备工作

进入到SparkShell命令行

/export/servers/spark/bin/spark-shell --master spark://node01:7077,node02:7077

创建一个样例类,用于封装数据

case class Score(name: String, clazz: Int, score: Int)

创建一个RDD数组,造一些数据,并调用toDF方法将其转换成DataFrame

val scoreDF = spark.sparkContext.makeRDD(Array(
Score("a1", 1, 80),
Score("a2", 1, 78),
Score("a3", 1, 95),
Score("a4", 2, 74),
Score("a5", 2, 92),
Score("a6", 3, 99),
Score("a7", 3, 99),
Score("a8", 3, 45),
Score("a9", 3, 55),
Score("a10", 3, 78),
Score("a11", 3, 100))
).toDF("name", "class", "score")

创建一个临时表

scoreDF.createOrReplaceTempView("scores")

查询所有数据

scoreDF.show()
+----+-----+-----+
|name|class|score|
+----+-----+-----+
| a1|    1| 80|
| a2|    1| 78|
| a3|    1| 95|
| a4|    2| 74|
| a5|    2| 92|
| a6|    3| 99|
| a7|    3| 99|
| a8|    3| 45|
| a9|    3| 55|
| a10|    3| 78|
| a11|    3| 100|
+----+-----+-----+

3. 聚合开窗函数

示例1

OVER 关键字表示把聚合函数当成聚合开窗函数而不是聚合函数。

SQL标准允许将所有聚合函数用做聚合开窗函数。

spark.sql("select  count(name)  from scores").show spark.sql("select name, class, score, count(name) over() name_count from scores").show

查询结果如下所示:

查询结果如下所示:
+----+-----+-----+----------+                                                   
|name|class|score|name_count|
+----+-----+-----+----------+
| a1|    1| 80|        11| |  a2| 1|   78| 11|
| a3|    1| 95|        11| |  a4| 2|   74| 11|
| a5|    2| 92|        11| |  a6| 3|   99| 11|
| a7|    3| 99|        11| |  a8| 3|   45| 11|
| a9|    3| 55|        11| | a10| 3|   78| 11|
| a11|    3| 100|        11| +----+-----+-----+----------+

示例2

OVER 关键字后的括号中还可以添加选项用以改变进行聚合运算的窗口范围。

如果 OVER 关键字后的括号中的选项为空,则开窗函数会对结果集中的所有行进行聚合运算。

开窗函数的 OVER 关键字后括号中的可以使用 PARTITION BY 子句来定义行的分区来供进行聚合计算。与 GROUP BY 子句不同,PARTITION BY 子句创建的分区是独立于结果集的,创建的分区只是供进行聚合计算的,而且不同的开窗函数所创建的分区也不互相影响。

 

下面的 SQL 语句用于显示按照班级分组后每组的人数:

 

OVER(PARTITION BY class)表示对结果集按照 class 进行分区,并且计算当前行所属的组的聚合计算结果。

spark.sql("select name, class, score, count(name) over(partition by class) name_count from scores").show

查询结果如下所示:

+----+-----+-----+----------+                                                   
|name|class|score|name_count|
+----+-----+-----+----------+
| a1|    1| 80|         3| |  a2| 1|   78| 3|
| a3|    1| 95|         3| |  a6| 3|   99| 6|
| a7|    3| 99|         6| |  a8| 3|   45| 6|
| a9|    3| 55|         6| | a10| 3|   78| 6|
| a11|    3| 100|         6| |  a4| 2|   74| 2|
| a5|    2| 92|         2| +----+-----+-----+----------+ 

4. 排序开窗函数

4.1 ROW_NUMBER顺序排序

row_number() over(order by score) as rownum 表示按score 升序的方式来排序,并得出排序结果的序号

 

注意:

在排序开窗函数中使用 PARTITION BY 子句需要放置在ORDER BY 子句之前。

示例1

 

spark.sql("select name, class, score, row_number() over(partition by class order by score) rank from scores").show()
+----+-----+-----+----+                                                         
|name|class|score|rank|
+----+-----+-----+----+
| a2|    1| 78|   1| |  a1| 1|   80| 2|
| a3|    1| 95|   3| |  a8| 3|   45| 1|
| a9|    3| 55|   2| | a10| 3|   78| 3|
| a6|    3| 99|   4| |  a7| 3|   99| 5|
| a11|    3| 100|   6| |  a4| 2|   74| 1|
| a5|    2| 92|   2| +----+-----+-----+----+

 

4.2 RANK跳跃排序

rank() over(order by score) as rank表示按 score升序的方式来排序,并得出排序结果的排名号。

 

这个函数求出来的排名结果可以并列(并列第一/并列第二),并列排名之后的排名将是并列的排名加上并列数

 

简单说每个人只有一种排名,然后出现两个并列第一名的情况,这时候排在两个第一名后面的人将是第三名,也就是没有了第二名,但是有两个第一名。

实例2

spark.sql("select name, class, score, rank() over(order by score) rank from scores").show()                                                     
+----+-----+-----+----+
|name|class|score|rank|
+----+-----+-----+----+
| a8|    3| 45|   1| |  a9| 3|   55| 2|
| a4|    2| 74|   3| | a10| 3|   78| 4|
| a2|    1| 78|   4| |  a1| 1|   80| 6|
| a5|    2| 92|   7| |  a3| 1|   95| 8|
| a6|    3| 99|   9| |  a7| 3|   99| 9|
| a11|    3| 100|  11| +----+-----+-----+----+ 
spark.sql("select name, class, score, rank() over(partition by class order by score) rank from scores").show()
+----+-----+-----+----+                                                         
|name|class|score|rank|
+----+-----+-----+----+
| a2|    1| 78|   1| |  a1| 1|   80| 2|
| a3|    1| 95|   3| |  a8| 3|   45| 1|
| a9|    3| 55|   2| | a10| 3|   78| 3|
| a6|    3| 99|   4| |  a7| 3|   99| 4|
| a11|    3| 100|   6| |  a4| 2|   74| 1|
| a5|    2| 92|   2| +----+-----+-----+----+

4.3 DENSE_RANK连续排序

dense_rank() over(order by score) as dense_rank 表示按score 升序的方式来排序,并得出排序结果的排名号。

 

这个函数并列排名之后的排名是并列排名加1

 

简单说每个人只有一种排名,然后出现两个并列第一名的情况,这时候排在两个第一名后面的人将是第二名,也就是两个第一名,一个第二名

 

实例3

spark.sql("select name, class, score, dense_rank() over(order by score) rank from scores").show()
+----+-----+-----+----+
|name|class|score|rank|
+----+-----+-----+----+
| a8|    3| 45|   1| |  a9| 3|   55| 2|
| a4|    2| 74|   3| |  a2| 1|   78| 4|
| a10|    3| 78|   4| |  a1| 1|   80| 5|
| a5|    2| 92|   6| |  a3| 1|   95| 7|
| a6|    3| 99|   8| |  a7| 3|   99| 8|
| a11|    3| 100|   9| +----+-----+-----+----+
spark.sql("select name, class, score, dense_rank() over(partition by class order by score) rank from scores").show()
+----+-----+-----+----+                                                         
|name|class|score|rank|
+----+-----+-----+----+
| a2|    1| 78|   1| |  a1| 1|   80| 2|
| a3|    1| 95|   3| |  a8| 3|   45| 1|
| a9|    3| 55|   2| | a10| 3|   78| 3|
| a6|    3| 99|   4| |  a7| 3|   99| 4|
| a11|    3| 100|   5| |  a4| 2|   74| 1|
| a5|    2| 92|   2| +----+-----+-----+----+

4.4 NTILE分组排名

ntile(6) over(order by score)as ntile表示按 score 升序的方式来排序,然后 6 等分成 6 个组,并显示所在组的序号。

实例4

spark.sql("select name, class, score, ntile(6) over(order by score) rank from scores").show()
+----+-----+-----+----+
|name|class|score|rank|
+----+-----+-----+----+
| a8|    3| 45|   1| |  a9| 3|   55| 1|
| a4|    2| 74|   2| |  a2| 1|   78| 2|
| a10|    3| 78|   3| |  a1| 1|   80| 3|
| a5|    2| 92|   4| |  a3| 1|   95| 4|
| a6|    3| 99|   5| |  a7| 3|   99| 5|
| a11|    3| 100|   6| +----+-----+-----+----+
spark.sql("select name, class, score, ntile(6) over(partition by class order by score) rank from scores").show()
+----+-----+-----+----+                                                         
|name|class|score|rank|
+----+-----+-----+----+
| a2|    1| 78|   1| |  a1| 1|   80| 2|
| a3|    1| 95|   3| |  a8| 3|   45| 1|
| a9|    3| 55|   2| | a10| 3|   78| 3|
| a6|    3| 99|   4| |  a7| 3|   99| 5|
| a11|    3| 100|   6| |  a4| 2|   74| 1|
| a5|    2| 92|   2| +----+-----+-----+----+

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/43388.html

相关文章

首次商业化,视频号“竖屏看春晚”获 1.9 亿人观看 | 微信广告

首次商业化,视频号“竖屏看春晚”获 1.9 亿人观看 | 微信广告

除夕夜,你在视频号竖屏看春晚了吗? 今年春节,中央广播电视总台与视频号二度合作“竖屏看春晚”,超 1.9 亿用户在视频号直播间共享这场沉浸式文化盛宴,场观破亿速度较去年提前 1.5 小时,直播间喝彩次数高达 3.79 亿,直播间分享次数近 1000 万......多项数据创视频号直播新...

三大人气行业抖音“营销套路”

三大人气行业抖音“营销套路”

导语 :前段时间网络流行语“抖音带我看世界”说出了小编的心声,自从迷上了抖音,小编就想去哈尔滨看冰雕、去西安喝摔碗酒、去郑州买答案茶、去重庆坐轻轨.....抖音一夜之间火遍大江南北,各大企业为争取流量红利也纷纷入驻抖音。而你所不知道的是,你点赞的各种萌宠、高颜值、逗趣的短视...

小红书信息流广告如何投放?取成本实现持续增长!

小红书信息流广告如何投放?取成本实现持续增长!

电子商务的新时代已经开始。“小红书每天发包裹7000多万件,约占全国的三分之一。小红书推广公司CEO陈雷在国家扶贫奖表彰大会结束后接受采访时透露,“十一”长假前后,10月17日,小红书日均订单量峰值突破1亿。投放根据国家邮政局邮政行业安全监管信息系统18日的实时监测数据显示,我国第60期快件于202...

bonjour被卸载了会怎样(sw安装bonjour出问题的后果)

bonjour被卸载了会怎样(sw安装bonjour出问题的后果)

电脑用户使用电脑的时候发现电脑上Bonjour被关闭了,用户不知道怎么解决,今天为大家分享win10系统Bonjour关闭了的解决方法。   1、打开电脑控制面板。如图所示:       2、选择小图标模式打开管理工具。如图所示:  ...

小红书流量能赚多少钱?小红书玩法教程

小红书流量能赚多少钱?小红书玩法教程

小红书流量能赚多少钱?小红书玩法教程 小红书流量能赚多少钱? 小红书的阅读量没有收入,需要做流量转化,比如接收广告、直播带货等,可以把流量转化为金钱。毕竟阅读量越高,关注度越高,看的人越多,看的人越多,推荐的产品曝光率就越高。 小红书有哪些玩法? 1....

淘宝新主播如何找商家合作?前期怎么熬?

淘宝新主播如何找商家合作?前期怎么熬?

淘宝新主播如何找商家合作?前期怎么熬? 如何与商家合作? 1、可通过淘宝联盟搜索商家推广计划,寻找需要直播的商家。 2、登录阿里妈妈淘宝联盟,点击超级搜索寻找需要直播的商家。 3.可以直接找到自己想推广带货的产品申请推广计划。你可以在淘宝直播中添加推广...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片