【问题标题】:cumulative distinct count in hive蜂巢中的累积不同计数
【发布时间】:2014-07-26 22:25:08
【问题描述】:

这是来自表 daily_user 的一些示例数据。每行代表一个特定日期的活跃用户,收入基于该用户当天产生的钱。此表中最早的日期是 1/1。

date user_id group revenue  
1/1  1       a     1  
1/1  2       b     0  
1/1  3       a     0  
1/2  2       b     10  
1/2  3       a     0  
1/3  3       a     1  

我想要的输出(基本上,每一行告诉我每个组,从 1/1 到每个观察日期,有多少用户曾经付费。例如,最后一行表示从 1/1-1/3,对于 b 组,我们总共有 1 个用户向我们付款):

end_date    group     # users who ever paid  
1/1          a             1  
1/1          b             0   
1/2          a             1  
1/2          b             1  
1/3          a             2  
1/3          b             1  

似乎有一些 UDF 可以进行累积求和,但我不确定我是否可以在这里利用任何累积非重复计数函数。反正有没有构造一个蜂巢查询来实现这个?

【问题讨论】:

  • 您是指累积distinct计数还是累积折扣计数?
  • 我的意思是不同的,谢谢!

标签: count hive distinct cumulative-sum


【解决方案1】:

我认为解决方案实际上是“收集_设置”用户(收集唯一值)并获取数组的大小,以供少量用户使用(即适合内存)

SELECT size( collect_set( user_id ) ) as uniques
       end_date, group
FROM daily_user
GROUP BY end_date, group;

对于大量唯一性,您需要一个概率数据结构,如草图集或超日志,可作为 UDF 从 Brickhouse 库 (http://github.com/klout/brickhouse) 获得。这将为您提供一个接近的估计值,但不是唯一的确切数量

SELECT estimated_reach( sketch_set( user_id )) as uniques_est,
       end_date, group
FROM daily_user
GROUP BY end_date, group;

您也可以合并这些,以便合并前几天预先计算的集合/草图。类似的东西:

SELECT size(combine_unique( unique_set ) ) as uniques,
      group
FROM daily_uniques
WHERE end_date > date_add( today, -30 )
GROUP BY group;

SELECT estimated_reach( union_sketch( unique_sketch) ) as uniques,
       group
FROM daily_uniques
WHERE end_date > date_add( today, -30 )
GROUP BY group;

【讨论】:

    【解决方案2】:

    如果收益为 0,函数if(revenue=0,1,0) 的值为 1,否则为 0。对这个函数求和会得到收入为 0 的总人数:

    select
      date as end_date,
      group,
      sum(if(revenue=0,1,0)) as number_of_users_who_never_paid
    from
      daily_user
    group by
      date,
      group
    

    【讨论】:

    • 谢谢 Jason,我实际上对获取累计付款人数量更感兴趣。
    【解决方案3】:

    不编写自定义 UDF 的最简单方法是进行某种笛卡尔连接:

    select
      date as end_date,
      group,
      sum(if(mon.user_id is not null AND mon.date <= du.date,1,0)) as cumulative_spenders
    from
      daily_user du
    LEFT OUTER JOIN
      (
       select
         distinct
         user_id,
         date,
         group
       from
         daily_user 
       where
         revenue > 0
       ) mon
    ON
      (du.user_id=mon.user_id and du.group=mon.group)
    group by
      date,
      group    
    

    这将在原始表中的每个条目的每个支出事务中生成一行,然后从那里聚合。

    【讨论】:

    • 如果我错了,请纠正我,对于每个用户来说,cumulative_spenders 是唯一的吗?看来 user_id 1 的查询结果中仍然会有多行
    • 是的,这是真的 - 添加了一个可以解决问题的不同
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-07
    相关资源
    最近更新 更多