概述

https://www.cnblogs.com/qiuting/p/7880500.html

  • 介绍:
    开窗函数的引入是为了既显示聚集前的数据,又显示聚集后的数据。即在每一行的最后一列添加聚合函数的结果。
    开窗用于为行定义一个窗口(这里的窗口是指运算将要操作的行的集合),它对一组值进行操作,不需要使用 GROUP BY 子句对数据进行分组,能够在同一行中同时返回基础行的列和聚合列。
  • 聚合函数和开窗函数
    聚合函数是将多行变成一行,count,avg…
    开窗函数是将一行变成多行;
    聚合函数如果要显示其他的列必须将列加入到group by中
    开窗函数可以不使用group by,直接将所有信息显示出来
  • 开窗函数分类
  1. 聚合开窗函数
    聚合函数(列) OVER(选项),这里的选项可以是PARTITION BY 子句,但不可以是 ORDER BY 子句。
  2. 排序开窗函数
    排序函数(列) OVER(选项),这里的选项可以是ORDER BY 子句,也可以是 OVER(PARTITION BY 子句 ORDER BY 子句),但不可以是 PARTITION BY 子句。

准备工作

/export/servers/spark/bin/spark-shell --master spark://node01:7077,node02:7077case class Score(name: String, clazz: Int, score: Int)
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|
+----+-----+-----+

聚合开窗函数

示例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|
+----+-----+-----+----------+

排序开窗函数

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(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|   5|
|  a1|    1|   80|   6|
|  a5|    2|   92|   7|
|  a3|    1|   95|   8|
|  a6|    3|   99|   9|
|  a7|    3|   99|  10|
| a11|    3|  100|  11|
+----+-----+-----+----+
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|
+----+-----+-----+----+

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|
+----+-----+-----+----+

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|
+----+-----+-----+----+

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|
+----+-----+-----+----+

Spark SQL:从入门到精通(五)[开窗函数]相关推荐

  1. Spark SQL 快速入门系列(五)SparkSQL 访问 Hive

    文章目录 访问 Hive SparkSQL 整合 Hive 访问 Hive 表 idea实现SparkSQL连接hive 访问 Hive 导读 1,整合 SparkSQL 和 Hive, 使用 Hiv ...

  2. Spark SQL:从入门到精通(一)[SparkSQL初体验]

    入口-SparkSession 在spark2.0版本之前 SQLContext是创建DataFrame和执行SQL的入口 HiveContext通过hive sql语句操作hive表数据,兼容hiv ...

  3. Kali Linux 从入门到精通(五)-测试环境准备

    Kali Linux 从入门到精通(五)-测试环境准备 准备实验环境 渗透非系统授权的弊端 搭建自己的实验环境 安装虚拟机 微软最新软件 http://msdn.microst.com/en-ca/s ...

  4. SQL由入门到精通的学习

    SQL 21 日自学通(V1.0) 翻译人笨猪 EMAIL wyhsillypig@163.com 1 目录 目录........................................... ...

  5. spark SQL快速入门 1-9 慕课网

    1.hadoop安装 1.修改hadoop配置文件hadoop-env.shexport JAVA_HOME=/home/hadoop/app/jdk1.8.0_91core-site.xml< ...

  6. spark SQL压缩入门

    parquet 默认压缩格式:snappy 可用压缩格式:none, snappy, gzip, lzo 默认是snappy压缩的parquet格式,不指定的情况下 保存为gzip压缩的parquet ...

  7. 数据分析(SQL)常见面试题:开窗函数

    一.什么是开窗函数 开窗函数/分析函数:over()        开窗函数也叫分析函数,有两类:一类是聚合开窗函数,一类是排序开窗函数. 开窗函数的调用格式为: 函数名(列名) OVER(parti ...

  8. ORACLE系列之SQL从入门到精通(全面把控数据库基础)

    2019独角兽企业重金招聘Python工程师标准>>> 学习目标:                 1.了解设计数据库的步骤                2.掌握如何绘制数据库的E ...

  9. Drf从入门到精通五(2个视图基类、5个视图拓展类、9个视图子类、视图集)

    文章目录 一.2个视图基类 1) 基于AIPView写5个接口 2) 基于GenericAPIView写5个接口 二.5个视图拓展类 1) 基于GenericAPIView+5个视图拓展类写接口 三. ...

最新文章

  1. 使用三防漆来保护PCB的敷铜面
  2. 把java 工程转为 maven 工程
  3. 机器学习实验中的编程技术(part4)--模型持久化
  4. javascript 里Array的一些方法
  5. ajax会占用服务器端内存吗,javascript - 为什么不允许在jquery datatable服务器端处理ajax成功使用? - 堆栈内存溢出...
  6. 人的“肥胖”基因FTO可促进水稻和土豆增产50% - 中国粮食、中国饭碗
  7. thrift使用传输协议TCompactProtocol - xiaoshe的专栏 - 博客频道 - CSDN.NET
  8. go的goroutine像水一样自然
  9. Tomcat学习总结(8)——Tomcat+Nginx集群解决均衡负载及生产环境热部署
  10. 帆软报表-通过代码来创建一个模板文件
  11. Web API-定时器
  12. MFC显示位图和显示透明位图
  13. 2019年8月 华为鸿蒙,华为2019年开发者大会将于8月9日举行,期待鸿蒙吗?
  14. linux翻页查看,【转载】linux-查看日志
  15. 【线性代数笔记】关于两个矩阵相乘等于零矩阵(AB=O)
  16. 《雪中悍刀行》读后感
  17. conda常用命令(换源清华源,创建虚拟环境)
  18. IMAX重开369家中国影院;康希诺辉瑞签署疫苗推广服务协议 | 美通企业日报
  19. 谷歌protobuf(Protocol buffers)的使用
  20. Marvolo Gaunt's Ring CodeForces - 855B+线段树+维护区间最大值和最小值

热门文章

  1. 如何在WordPress网站上轻松显示代码
  2. 关于微信小程序this.setData不渲染问题
  3. swing QQ游戏大厅
  4. Windows Server 2012 R2 安装网卡驱动(ethernet connection i219-v)
  5. [java] implements
  6. 高端笔记本电脑轻薄本推荐之XPS 13
  7. 用计算机用语说唯美的话,很美的唯美说说句子
  8. 解决idea中的application.properties文件没有变成叶子形状
  9. face_recognition使用:人脸识别开源python库(face_recognition是基于dlib的深度学习人脸识别库)
  10. GitHub标星9,Android工程师跳槽经验分享