Spark分组取TopN

前言

说到分组,我们很快就想到group by,但是如果在分组的基础上进行取TopN,我们很快又想到开窗函数,group by一般和聚合函数搭配使用,那么聚合函数和开窗函数有啥区别呢?

普通的聚合函数聚合的行集是组,开窗函数聚合的行集是窗口。因此,普通的聚合函数每组(Group by)只返回一个值,而开窗函数则可为窗口中的每行都返回一个值。简单理解,就是对查询的结果多出一列,这一列可以是聚合值,也可以是排序值。
开窗函数一般分为两类,聚合开窗函数和排序开窗函数。
接下来通过几个简单的案例来看使用Spark如何求分组取TopN的需求

案例一(没有聚合函数取TopN)

  • 准备数据
//company app visit_times
腾讯,腾讯视频,800
腾讯,QQ音乐,900
腾讯,微信读书,100
腾讯,微信,900
腾讯,腾讯课堂,200
阿里,支付宝,900
阿里,优酷视频,700
阿里,虾米音乐,500
阿里,飞猪,700
阿里,钉钉,600
百度,百度App,700
百度,百度地图,800
百度,爱奇艺,800
百度,百度钱包,100
百度,百度贴吧,200
  • 程序入口SparkSession和加载数据代码这里不再描述:
val spark = SparkSession
      .builder()
      .appName(this.getClass.getSimpleName)
      .master(master = "local[*]")
      .getOrCreate()

    import spark.implicits._
    val df = spark.read.textFile("./data/app")
      .map(_.split(","))
      .map(x => (x(0), x(1), x(2)))
      .toDF("company", "app", "vst_times")
      .cache()
  • 需求:取出BAT三大公司访问量Top2的app
df.createTempView(viewName = "view1")
    import spark.sql
    sql(sqlText = "select company,app,vst_times from " +
      "(select company,app,vst_times,row_number() " +
      "over(partition by company order by vst_times desc) " +
      "as rn from view1) as t  where t.rn <= 2")
      .show()

这里使用的是Hive的row_number()函数,语法格式:
row_number() over (partition by COL1 order by COL2 desc ) rank

结果:

+-------+--------+---------+
|company|     app|vst_times|
+-------+--------+---------+
|   腾讯|  QQ音乐|      900|
|   腾讯|    微信|      900|
|   百度|百度地图|      800|
|   百度|  爱奇艺|      800|
|   阿里|  支付宝|      900|
|   阿里|优酷视频|      700|
+-------+--------+---------+

案例二(需要先做聚合后取TopN)

  • 准备数据
腾讯,微信,500
腾讯,微信,800
腾讯,微信,1000
腾讯,微信,600
腾讯,腾讯视频,800
腾讯,腾讯视频,300
腾讯,腾讯视频,700
腾讯,腾讯视频,700
腾讯,QQ音乐,900
腾讯,QQ音乐,500
腾讯,QQ音乐,900
腾讯,QQ音乐,600
腾讯,微信读书,100
腾讯,微信读书,200
腾讯,微信读书,300
腾讯,微信读书,100
腾讯,腾讯课堂,100
腾讯,腾讯课堂,200
腾讯,腾讯课堂,300
腾讯,腾讯课堂,100
  • 需求:统计出腾讯系总访问次数前三的app
import org.apache.spark.sql.functions._
    df.select("company", "app", "vst_times")
      .groupBy("company", "app")
      .agg(sum($"vst_times").alias("s_vst"))
      .sort($"s_vst".desc)
      .limit(3)
      .show()

结果:

+-------+--------+------+
|company|     app| s_vst|
+-------+--------+------+
|   腾讯|  QQ音乐|2900.0|
|   腾讯|    微信|2900.0|
|   腾讯|腾讯视频|2500.0|
+-------+--------+------+

你可能感兴趣的:(Spark)