【问题标题】:Hive window function : assigning group id to overlapping groupHive 窗口功能:将组 id 分配给重叠组
【发布时间】:2019-12-06 13:19:16
【问题描述】:

我在 hive 表中的数据如下所示,其中 id 、 start_time 和 end_time 作为字符串

id   start_time   end_time
101  10:00        12:00
101  10:15        12:30
101  12:15        12:45
101  13:00        14:00
102  10:15        10:30

我想创建一个新字段 group_id 来标识每个“id”中具有重叠 start_time 和 end_time 间隔的记录。 期望的输出是:

id   start_time   end_time group_id
101  10:00        12:00     1
101  10:15        12:30     1
101  12:15        12:45     1
101  13:00        14:00     2
102  10:15        10:30     3

例如:在 101 内,第 1 3 条记录重叠: 第 2 次与第 1 次重叠,因为 10:15(第 2 次的开始时间)在 10:00 和 12:00(第 1 次的开始和结束时间)之间。 第 3 次与第 2 次重叠,因为 12:15(第 3 次的开始时间)在 10:15 和 12:30(第 2 次的开始和结束时间)之间。 第 4 条记录不重叠,因此被分配下一个组 ID (2)。 最后一条记录具有不同的 id 并且单独在组中,因此它被赋予下一个 id (3)

我尝试将一条记录与之前的记录进行比较,以检查它是否使用滞后函数重叠:

select id, start_time,end_time,
    case when rownum_per_id = 1 THEN 'TRUE'
         when start_time between lag(start_time,1) over w and lag(end_time,1) over w THEN 'TRUE'
         ELSE 'FALSE' END as overlap_ind
from 
    (select id,start_time,end_time,
        row_number() over(partition by id order by start_time) as rownum_per_id
     from (select id,
             from_unixtime(unix_timestamp(start_time,"HH:mm")) as start_time,
             from_unixtime(unix_timestamp(end_time,"HH:mm")) as end_time
           from test_table
         ) a
    ) b
window w as (partition by id order by start_time)

得到输出为:

id  start_time          end_time            overlap_ind
101 1970-01-01 10:00:00 1970-01-01 12:00:00 TRUE
101 1970-01-01 10:15:00 1970-01-01 12:30:00 TRUE
101 1970-01-01 12:15:00 1970-01-01 12:45:00 TRUE
101 1970-01-01 13:00:00 1970-01-01 14:00:00 FALSE
102 1970-01-01 10:15:00 1970-01-01 10:30:00 TRUE

但无法弄清楚下一步如何分配递增的 group_id

【问题讨论】:

    标签: sql hive hiveql


    【解决方案1】:

    您可以为此使用字符串操作。一种方法是计算每次之前的累积最大值。使用该信息来确定小组何时开始——然后是累积总和:

    select t.*,
           sum(case when prev_end_time >= start_time then 0
                    else 1 end) over (partition by id order by start_time) as group_id
    from (select t.*,
                 max(end_time) over (partition by id order by start_time rows between unbounded preceding and 1 preceding) as prev_end_time
          from finance_acturl_data_smith.test_table t
         ) t;
    

    编辑:

    上面为每个用户生成一个单独的group_id。我们可以通过删除partition by来调整它:

    select t.*,
           sum(case when prev_end_time >= start_time then 0
                    else 1 end) over (order by id, start_time) as group_id
    from (select t.*,
                 max(end_time) over (partition by id order by start_time rows between unbounded preceding and 1 preceding) as prev_end_time
          from finance_acturl_data_smith.test_table t
         ) t;
    

    这是可行的,因为第一个 partition by 仍用于定义 prev_end_time,因此每个 id 的第一个值是 NULL 并转到 else

    【讨论】:

    • 内部查询在 Hive 中给出语法错误:SemanticException End of a WindowFrame cannot be UNBOUNDED PRECEDING (state=42000,code=40000)
    • @Shanil 。 . .不仅是这个标准 SQL,而且 Hive 也明确支持它:cwiki.apache.org/confluence/display/Hive/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 2012-05-05
    相关资源
    最近更新 更多