在Hive SQL

时间:2016-09-07 16:40:48

标签: oracle postgresql hadoop hive

我有数据,

ID  time
1   9/6/2016 00:01:00
1   9/6/2016 00:01:30
1   9/6/2016 00:02:00
1   9/6/2016 00:04:30
1   9/6/2016 00:05:30
1   9/6/2016 01:05:30
1   9/6/2016 05:05:30
1   9/6/2016 05:06:30
2   9/6/2016 01:55:00
2   9/6/2016 01:56:29
2   9/6/2016 01:57:31
2   9/6/2016 03:55:00
2   9/6/2016 04:13:00
2   9/6/2016 04:15:21

对于每个ID,我想将一个名为flag的新变量设置为1,并检查第一个时间值。从第一个时间值开始,我想检查第一个条目3分钟内的条目,并将每个条目设置为1.一旦时间条目超过3分钟,我想将flag变量设置为2然后再次检查从那时起3分钟内的条目,这需要继续每个ID。我想为每个ID找到3分钟组,以便我可以为每个ID形成集合。

我想要的输出是,

ID  time              flag
1   9/6/2016 00:01:00   1
1   9/6/2016 00:01:30   1
1   9/6/2016 00:02:00   1
1   9/6/2016 00:04:30   2
1   9/6/2016 00:05:30   2
1   9/6/2016 01:05:30   2
1   9/6/2016 05:05:30   2
1   9/6/2016 05:06:30   2
2   9/6/2016 01:55:00   1
2   9/6/2016 01:56:29   1
2   9/6/2016 01:57:31   1
2   9/6/2016 03:55:00   2
2   9/6/2016 04:13:00   3
2   9/6/2016 04:15:21   3

此处对于ID 1,标志设置为1并持续检查3分钟条目直到第3行,一旦超过3分钟,它将设置为2并再次开始检查3分钟条目。同样对于ID 2也是如此。

以下是我的尝试,

select ID, time, rank() over (order by time) as rank from table_name;

这是整个表的排名。我在想,我们可以为每个ID排名,然后调用第一个值并用剩余值减去它,并在此处写一个子查询。

有更好的有效方法吗?我在这里使用Hive查询。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

您可以查看DataFu中的sessonize UDF

此外,还有一篇关于可用{hm,pig,python}的不同选项的帖子here

答案 1 :(得分:0)

请注意,您的样本输出不正确;对于ID = 1,时间= 01:05:30是00:05:30之后的整整一小时,但两者都有相同的标志。

这是一个专门使用Oracle SQL的解决方案。检查“标志转换”条件;我写它的方式,新标志只有在严格超过3分钟后才开始。如果您想在3分钟过后开始新计数,请将第一个不等式更改为非严格,将第二个不等式更改为严格。

解决方案*使用递归因子子查询,因此需要Oracle 11.2或更高版本。

*注意:从逻辑上讲,我不应该在我所做的地方减去3 /(24 * 60);相反,不等式应与3 /(24 * 60)进行比较。这适用于Oracle 12,但是它使用ORA-00600崩溃了Oracle 11.2上的数据库,我被告知这是11.2中Oracle递归查询实现中已知错误的标记(已在12.1中修复)。我是非付费客户,所以我自己无法访问错误信息。我在Oracle 11.2上测试了我在下面发布的查询并且它可以工作,而简化版本崩溃了。这两个版本在12.1上运行良好。

with
     inputs ( id, time ) as (
       select 1, to_date('9/6/2016 00:01:00', 'mm/dd/yyyy hh24:mi:ss') from dual union all
       select 1, to_date('9/6/2016 00:01:30', 'mm/dd/yyyy hh24:mi:ss') from dual union all
       select 1, to_date('9/6/2016 00:02:00', 'mm/dd/yyyy hh24:mi:ss') from dual union all
       select 1, to_date('9/6/2016 00:04:30', 'mm/dd/yyyy hh24:mi:ss') from dual union all
       select 1, to_date('9/6/2016 00:05:30', 'mm/dd/yyyy hh24:mi:ss') from dual union all
       select 1, to_date('9/6/2016 01:05:30', 'mm/dd/yyyy hh24:mi:ss') from dual union all
       select 1, to_date('9/6/2016 05:05:30', 'mm/dd/yyyy hh24:mi:ss') from dual union all
       select 1, to_date('9/6/2016 05:06:30', 'mm/dd/yyyy hh24:mi:ss') from dual union all
       select 2, to_date('9/6/2016 01:55:00', 'mm/dd/yyyy hh24:mi:ss') from dual union all
       select 2, to_date('9/6/2016 01:56:29', 'mm/dd/yyyy hh24:mi:ss') from dual union all
       select 2, to_date('9/6/2016 01:57:31', 'mm/dd/yyyy hh24:mi:ss') from dual union all
       select 2, to_date('9/6/2016 03:55:00', 'mm/dd/yyyy hh24:mi:ss') from dual union all
       select 2, to_date('9/6/2016 04:13:00', 'mm/dd/yyyy hh24:mi:ss') from dual union all
       select 2, to_date('9/6/2016 04:15:21', 'mm/dd/yyyy hh24:mi:ss') from dual
     ),
     rec ( id, time, flag, time_diff ) as (
       select  id, time, 1, 
               time - min(time) over (partition by id order by time) - 3/(24*60)
         from  inputs
       union all
       select  id, time, flag + 1, 
               time - min(time) over (partition by id order by time) - 3/(24*60)
         from  rec
         where time_diff > 0
     )
select   id, time, flag
from     rec
where    time_diff <= 0
order by id, time
;

<强>输出

  ID TIME                      FLAG
---- ------------------- ----------
   1 06/09/2016 00:01:00          1
   1 06/09/2016 00:01:30          1
   1 06/09/2016 00:02:00          1
   1 06/09/2016 00:04:30          2
   1 06/09/2016 00:05:30          2
   1 06/09/2016 01:05:30          3
   1 06/09/2016 05:05:30          4
   1 06/09/2016 05:06:30          4
   2 06/09/2016 01:55:00          1
   2 06/09/2016 01:56:29          1
   2 06/09/2016 01:57:31          1
   2 06/09/2016 03:55:00          2
   2 06/09/2016 04:13:00          3
   2 06/09/2016 04:15:21          3

 14 rows selected