Spark排序与取TopN问题

(一)TopN统计

一.Hive sql实现方法

需求描述:

根据活跃天数排名,选取每个用户使用的Top10的appid与app名称

思路解析:
1.使用row_number()函数达到排序目的
2.以用户的手机号为分组,(统计每一个用户的app排名),以活跃天数排序,排序字段命名为rn_vnt字段。并取出前十的app信息。
    sql(sqlText = s"select serv_number,prod_name,prod_id,statis_month,active_days,rn_vnt " +
      s"from (select serv_number,prod_name,prod_id," +
      s"statis_month,active_days,row_number() " +
      s"over(partition by serv_number order by active_days desc) as rn_vnt from " +
      s"profile_score_2i_visit_${this_month}_m ) t where t.rn_vnt <= '10'")
      .write.mode(SaveMode.Append).saveAsTable(tableName = s"total_visit_${this_month}_m")

输出结果(为保证数据安全,数据为模拟数据)

serv_numberprod_nameprod_idstatis_monthactive_daysrn_vnt
1366666666某app1C9999201905211
1366666666某app2C8888201905162
1366666666某app3C7777201905123

二.Spark sql实现方法

需求描述:

按照用户数排名,取出Top10的appid与app名称

思路解析:
1.首先引入spark中functions和implicits两个数据包
2.本例中需先统计每个app使用人数,使用人数命名字段为p_sum。之后对使用人数p_sum字段,进行降序排序
3.增加a_rank,表示app的排名。其中使用monotonically_increasing_id表示一个自增键,其是从0开始每一轮加一。monotonically_increasing_id+1来让app排名从1开始排名
4.使用limit(10)代表取出前10名的app
     import org.apache.spark.sql.functions._
     import spark.implicits._

     total_profile_score_df.select( "prod_id", "prod_name","statis_month","serv_number")
       .filter(s"prod_id <> 'C9999' ")   //统计中去除某app
       .groupBy("prod_id","prod_name","statis_month")
       .agg(count("serv_number").alias("p_sum"))
       .sort($"p_sum".desc)
       .withColumn("a_rank", monotonically_increasing_id+1)
       .limit(10)
       .createTempView(viewName = "total_app_view")

输出结果(为保证数据安全,数据为模拟数据)

prod_idprod_namestatis_monthp_suma_rankprovince_codeflag
C1111某app1201904999999991北京全量
C2222某app220190488888882北京全量
C3333某app32019047777773北京全量
C4444某app42019046666664北京全量

(二).百分之TopN统计

需求描述:

把指定的app,前20%访问次数的用户输出(对指定app的访问量的狂热用户)

思路解析:
1.首先计算出每个app前20%的用户数(top%n 相当于 top 中填入 n%的用户数)
2.使用row_number()函数,以app为分组,以用户对于app的访问次数排序,排序字段命名为rn_vnt字段。并取出前20%的使用当前app的用户信息。
//计算每个app的人数
    val c0 = sql(sqlText = s"select distinct serv_number " +
      s"from ads_app_bsn_${this_month}_m where prod_id = '${app_code(0)}'").count() * 0.2


    //App访问次数排名
    /**
      * 这里需要注意使用row_number()函数,要做分组取TopN的时候,必须再外围写
      * select * from () as t where t.rank <= x
      * 不然会报错
      * (写的有问题,由于row_number函数分组的时候额外加入了serv_number,导致维度有问题)
      * \t符号影响了排行,需要把手机号为\t的排除
      */

    sql(sqlText = s"select serv_number,prod_name,prod_id,statis_month " +
      s"from (select serv_number,prod_name,prod_id," +
      s"statis_month,row_number() " +
      s"over(partition by prod_name,prod_id order by visit_cnt desc) as rn_vnt from " +
      s"ads_app_bsn_${this_month}_m where prod_id = '${app_code(0)}') t where t.rn_vnt <= '$c0'")
      .write.mode(SaveMode.Overwrite).saveAsTable(tableName = s"ads_bsn_hobby_${this_month}_m")

输出结果(为保证数据安全,数据为模拟数据)

serv_numberprod_nameprod_idstatis_month
1366666666某app1C9999201905
1366664444某app1C9999201905
1366662222某app1C9999201905
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值