【问题标题】:Hive: calculating running DISTINCTHive:计算运行 DISTINCT
【发布时间】:2015-07-10 20:47:54
【问题描述】:

嗨,有没有办法计算 HIVE 中不同的运行计数?

我有一个数据框,其中包含日期和时间以及当前正在访问网站的人的 ID。

我想做的是知道不同的“累积”计数 id 按日期拆分。

我不能使用 group by dt, hour, count(distinct id) 因为如果玩家 在 1 和 2 处于活动状态,它将被计算两次。

有没有办法使用 Hive 分析和窗口化来做到这一点?

我试过了:

select date, hour, 
      count(distinct id) over( partition by date order by hrs rows between unbounded preceding and current row) users
from db.table

但它会引发错误。

【问题讨论】:

    标签: mysql hadoop hive


    【解决方案1】:

    你的直觉是正确的,Hive 只是不喜欢用窗口函数计算不同的值。解决方法是收集到一个集合,然后在窗口上获取每个数组的大小。我制作了一些随机数据以确保这是您想要的。说你有

    date        hour    user_id
    2015-01-01  1       1001
    2015-01-01  1       1001
    2015-01-01  2       1002
    2015-01-01  7       1003
    2015-01-02  4       1001
    2015-01-02  4       1001
    2015-01-02  5       1002
    2015-01-03  1       1004
    2015-01-03  3       1005
    2015-01-03  4       1001
    2015-01-03  4       1002
    

    查询

    select date
      , hour
      , size(collect_set(user_id) over (partition by date order by hour
                                        rows between unbounded preceding
                                        and current row)) users
    from db.table
    

    输出

    date        hour    users
    2015-01-01  1       1
    2015-01-01  1       1
    2015-01-01  2       2
    2015-01-01  7       3
    2015-01-02  4       1
    2015-01-02  4       1
    2015-01-02  5       2
    2015-01-03  1       1
    2015-01-03  3       2
    2015-01-03  4       3
    2015-01-03  4       4
    

    就性能而言,这需要 一个 MR 工作。在这种情况下,进行自左外连接是一场灾难。

    【讨论】:

      【解决方案2】:

      我认为您最好使用 case when 语句进行连接。

      那么你可以轻松做到以下几点:

      select a.date,
        count(DISTINCT CASE WHEN (prior_date < date) THEN b.id ELSE NULL END)
      from 
      my_table a
      left outer join
      (select date as prior_date, id from my_table) b
       on (1=1)
       where a.date > b.date
      ;
      

      这是一个假设日期是字符串可比的。您可以通过以下方式做到这一点,并假设您的日期都是最近的,因此字符串的大小相同。否则,您可能必须用零填充字符串。见下文:

      假设您的日期和时间类似于 yyyy-MM-dd 和 HH:mm:ss,然后将您的日期和时间转换为 unix_time_stamp,如下所示:

      unix_timestamp(concat_ws(" ", date, time)) as date
      

      【讨论】:

      • 感谢您的回答!但我想用一个窗口函数来做......并且想知道为什么我的语法是错误的?
      • 我认为这是因为窗口函数需要聚合函数。在 (...) 上使用 count(dinstinct(column)) 将聚合函数包装在 distinct 运算符周围。 distinct 运算符不是聚合函数,因此 distrinct(column) over (...) 失败。祝你好运卢卡塞隆! :)
      猜你喜欢
      • 2023-03-03
      • 1970-01-01
      • 2023-01-12
      • 1970-01-01
      • 1970-01-01
      • 2021-09-26
      • 1970-01-01
      • 1970-01-01
      • 2010-12-01
      相关资源
      最近更新 更多