我有数据,
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查询。任何帮助将不胜感激。
答案 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