關於SparkSQL的開窗函數,你應該知道這些!

1.概述

  • 介紹

        相信用過MySQL的朋友都知道,MySQL中也有開窗函數的存在。開窗函數的引入是爲了既顯示彙集前的數據,又顯示彙集後的數據。即在每一行的最後一列添加聚合函數的結果。javascript

        開窗用於爲行定義一個窗口(這裏的窗口是指運算將要操做的行的集合),它對一組值進行操做,不須要使用 GROUP BY 子句對數據進行分組,可以在同一行中同時返回基礎行的列和聚合列。java

        

  • 聚合函數和開窗函數

        聚合函數是將多行變成一行,count,avg…node

        開窗函數是將一行變成多行sql

        聚合函數若是要顯示其餘的列必須將列加入到group by中shell

        開窗函數能夠不使用group by,直接將全部信息顯示出來數組

  • 開窗函數分類

  1. 聚合開窗函數

        聚合函數(列) OVER(選項),這裏的選項能夠是PARTITION BY 子句,但不能夠是 ORDER BY 子句。markdown

  1. 排序開窗函數

        排序函數(列) OVER(選項),這裏的選項能夠是ORDER BY 子句,也能夠是OVER(PARTITION BY 子句 ORDER BY 子句),但不能夠是 PARTITION BY 子句ide

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

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

結語

        本次的分享就到這裏,受益的朋友或對大數據技術感興趣的夥伴能夠點個贊關注一下博主,後續會持續更新大數據的相關內容,敬請期待(✪ω✪)

在這裏插入圖片描述

相關文章
相關標籤/搜索