我们有几个单独的事件表。 对于给定的id,我们想知道2个事件之间的时差。 现在,对于给定的id,可能有几个相同的事件,我们只对“下一个”事件感兴趣。
示例:
http://sqlfiddle.com/#!4/1f724/6/0
模式
create table event_a (
timestmp timestamp(3),
id varchar2(50)
);
create table event_b (
timestmp timestamp(3),
id varchar2(50)
);
insert into event_a values (to_timestamp('2015-05-12 10:22:00', 'YYYY-MM-DD HH24:MI:SS'), 'x');
insert into event_b values (to_timestamp('2015-05-12 10:22:05', 'YYYY-MM-DD HH24:MI:SS'), 'x');
insert into event_a values (to_timestamp('2015-05-12 10:22:08', 'YYYY-MM-DD HH24:MI:SS'), 'x');
insert into event_b values (to_timestamp('2015-05-12 10:22:10', 'YYYY-MM-DD HH24:MI:SS'), 'x');
查询
这是我提出的查询,但在我看来有点过于复杂。我想知道是否有更好的方法来做到这一点。
如果这些表中有大量数据,此查询也需要很长时间才能运行。
select a.id, nvl((extract(day from (b.timestmp - a.timestmp)) * 86400
+ extract(hour from (b.timestmp - a.timestmp)) * 3600
+ extract(minute from (b.timestmp - a.timestmp)) * 60
+ extract(second from (b.timestmp - a.timestmp)) ), 0) as duration_in_sec
from event_a a
join event_b b on a.id = b.id and b.timestmp = (
select min(timestmp)
from event_b
where id = a.id
and timestmp >= a.timestmp
)
答案 0 :(得分:2)
你可以尝试这个,看看它是否有效/表现更好:
Select a.id, 86400 * (min(b.timestmp) - a.timestmp) diff
From event_a a
Join event_b b on a.id = b.id and b.timestmp >= a.timestmp
Group by a.id, a.timestmp
如果这对您不起作用,那么您几乎可以使用Group by:
进行旧查询Select a.id, nvl((extract(day from (min(b.timestmp) - a.timestmp)) * 86400
+ extract(hour from (min(b.timestmp) - a.timestmp)) * 3600
+ extract(minute from (min(b.timestmp) - a.timestmp)) * 60
+ extract(second from (min(b.timestmp) - a.timestmp)) ), 0) as duration_in_sec
From event_a a
Join event_b b on a.id = b.id and b.timestmp >= a.timestmp
Group by a.id, a.timestmp
答案 1 :(得分:2)
此解决方案应该更快,因为它没有自连接子查询:
select id, extract(day from (d)) * 86400 + extract(hour from (d)) * 3600
+ extract(minute from (d)) * 60 + extract(second from (d)) duration
from (
select a.id, b.timestmp - a.timestmp d,
row_number() over (partition by a.id, a.timestmp order by b.timestmp) rn
from event_a a
join event_b b on a.id = b.id and a.timestmp <= b.timestmp
order by a.timestmp)
where rn = 1
答案 2 :(得分:1)
如果event_a和event_b的时间戳总是替代,那么您可以使用:
WITH times AS (
SELECT id, timestmp, 1 AS event_type FROM event_a
UNION ALL
SELECT id, timestmp, 2 AS event_type FROM event_b
ORDER BY 1,2,3
),
timediffs AS (
SELECT id,
timestmp - LAG( timestmp ) OVER ( PARTITION BY id ORDER BY timestmp ASC, event_type ASC ) AS d,
event_type
FROM times
)
SELECT id,
extract(day from (d)) * 86400
+ extract(hour from (d)) * 3600
+ extract(minute from (d)) * 60
+ extract(second from (d)) AS duration
FROM timediffs
WHERE event_type = 2;