sparkSQL--over窗口函數(實戰案例)


一、over(窗口函數)

指的是對多行數據進行處理返回普通列和聚合列的過程

詳細語法:

窗口函數sql語法:窗口函數名()over (partition by 划分窗口字段 order by 窗口內的排序規則 rows between (start,end))

窗口函數分類:

  • 聚合窗口函數 aggregate 聚合類
  • 排名窗口函數 ranking 排名類
  • 數據分析窗口函數 analytic 分析類

參考鏈接:https://www.cnblogs.com/abc8023/p/10910741.html

Function Type SQL DataFrame API Description
Ranking rank rank rank值可能是不連續的
Ranking dense_rank denseRank rank值一定是連續的
Ranking percent_rank percentRank 相同的分組中 (rank -1) / ( count(score) - 1 )
Ranking ntile ntile 將同一組數據循環的往n個桶中放,返回對應的桶的index,index從1開始
Ranking row_number rowNumber 很單純的行號,類似excel的行號
Analytic cume_dist cumeDist
Analytic first_value firstValue 相同的分組中最小值
Analytic last_value lastValue 相同的分組中最大值
Analytic lag lag 取前n行數據
Analytic lead lead 取后n行數據
Aggregate min min 最小值
Aggregate max max 最大值
Aggregate sum sum 求和
Aggregate avg avg 求平均

二、具體用法如下

count(...) over(partition by ... order by ...) --求分組后的總數。
sum(...) over(partition by ... order by ...) --求分組后的和。
max(...) over(partition by ... order by ...) --求分組后的最大值。
min(...) over(partition by ... order by ...) --求分組后的最小值。
avg(...) over(partition by ... order by ...) --求分組后的平均值。
rank() over(partition by ... order by ...) --rank值可能是不連續的。
dense_rank() over(partition by ... order by ...) --rank值是連續的。
first_value(...) over(partition by ... order by ...) --求分組內的第一個值。
last_value(...) over(partition by ... order by ...) --求分組內的最后一個值。
lag() over(partition by ... order by ...) --取出前n行數據。
lead() over(partition by ... order by ...) --取出后n行數據。
ratio_to_report() over(partition by ... order by ...) --Ratio_to_report() 括號中就是分子,over() 括號中就是分母。
percent_rank() over(partition by ... order by ...)

三、應用案例

問題

某app訪問頁面的日志詳細記錄字段如下:day, user_id, page_id, time

求某天每個用戶訪問頁面次數前10的頁面。

("2018-01-01",1,"www.baidu.com","10:01"),
("2018-01-01",2,"www.baidu.com","10:01"),
("2018-01-01",1,"www.sina.com","10:01"),
("2018-01-01",3,"www.baidu.com","10:01"),
("2018-01-01",3,"www.baidu.com","10:01"),
("2018-01-01",1,"www.sina.com","10:01")

思路

  1. 每個用戶訪問不同頁面的次數

select user_id,page_id,count(page_id) from t_log group by user_id, page_id

+-------+-------------+-----+---+---|
|user_id| page_id|count|
+-------+-------------+-----+----+--|
| 2|www.baidu.com| 1|
| 3|www.baidu.com| 2|
| 1|www.baidu.com| 1|
| 1| www.sina.com| 2|
+-------+-------------+-----+----+--|

  1. 對每個用戶點擊頁面次數降序排列,並且使用窗口函數中的排名函數,對點擊頁面進行排名

w1:

| 1| www.sina.com| 2| 1

| 1|www.baidu.com| 1| 2

w2:

| 2|www.baidu.com| 1| 1

w3:

| 3|www.baidu.com| 2| 1

+-------+-------------+-----+----+
|user_id| page_id|count|rank|
+-------+-------------+-----+----+
| 1| www.sina.com| 2| 1|
| 1|www.baidu.com| 1| 2|
| 3|www.baidu.com| 2| 1|
| 2|www.baidu.com| 1| 1|
+-------+-------------+-----+----+

  1. 獲得每個用戶訪問次數前10的頁面

where rank <= 10

+-------+-------------+-----+----+
|user_id| page_id|count|rank|
+-------+-------------+-----+----+
| 1| www.sina.com| 2| 1|
| 1|www.baidu.com| 1| 2|
| 3|www.baidu.com| 2| 1|
| 2|www.baidu.com| 1| 1|
+-------+-------------+-----+----+

代碼

package method

import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.expressions.Window

object SQLDemo3 {
  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder().appName("sql operation").master("local[*]").getOrCreate()
    val rdd = spark.sparkContext.makeRDD(
      List(
        ("2018-01-01",1,"www.baidu.com","10:01"),
        ("2018-01-01",2,"www.baidu.com","10:01"),
        ("2018-01-01",1,"www.sina.com","10:01"),
        ("2018-01-01",3,"www.baidu.com","10:01"),
        ("2018-01-01",3,"www.baidu.com","10:01"),
        ("2018-01-01",1,"www.sina.com","10:01")
      )
    )
    import spark.implicits._
    val df = rdd.toDF("day","user_id","page_id","time")
  df.createTempView("t_log")
    //注意:""" 包裹內容 “”“自動進行字符串的拼接
    spark
      .sql(
        """
          |select *
          |from
          | (select user_id,page_id, num,
          |   rank() over(partition by user_id order by num desc) as rank
          |   from
          |     (select
          |       user_id,
          |       page_id,
          |       count(page_id) as num
          |       from t_log
          |       group by user_id,page_id))
          | where rank <= 10
          |
          |""".stripMargin
      )
      .show()
  spark.stop()
  }
}
//結果
+-------+-------------+---+----+
|user_id|      page_id|num|rank|
+-------+-------------+---+----+
|      1| www.sina.com|  2|   1|
|      1|www.baidu.com|  1|   2|
|      3|www.baidu.com|  2|   1|
|      2|www.baidu.com|  1|   1|
+-------+-------------+---+----+


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM