我有以下格式的数据,并希望以第二种格式输出。我已尝试在数据上进行自我加入,并通过id,时间和事件进行分组,但我尝试过的任何内容似乎都无法正常工作。
EV-2的时间是开始时间,EV-5的时间是结束时间。 EV-5时间可以写为每个EV-2-EV-5事件的结束时间。
感谢您对此事的任何指导。
ID TIME EVENT
1 2016-03-21 12:30:00.000 EV-1
1 2016-03-21 12:30:30.000 EV-2
1 2016-03-21 12:33:00.000 EV-3
1 2016-03-21 12:33:00.000 EV-4
1 2016-03-21 12:33:45.000 EV-5
1 2016-03-21 12:33:50.000 EV-1
1 2016-03-21 12:33:55.000 EV-2
1 2016-03-21 12:35:15.000 EV-3
1 2016-03-21 12:35:15.000 EV-4
1 2016-03-21 12:40:20.000 EV-5
2 2016-03-21 12:40:50.000 EV-1
2 2016-03-21 12:41:25.000 EV-2
2 2016-03-21 12:41:25.000 EV-3
2 2016-03-21 12:42:13.000 EV-4
2 2016-03-21 12:47:35.000 EV-5
Output
ID TIME(startTime) EVENT endTime
1 2016-03-21 12:30:00.000 EV-1
1 2016-03-21 12:30:30.000 EV-2 2016-03-21 12:33:45.000
1 2016-03-21 12:33:00.000 EV-3 2016-03-21 12:33:45.000
1 2016-03-21 12:33:00.000 EV-4 2016-03-21 12:33:45.000
1 2016-03-21 12:33:45.000 EV-5 2016-03-21 12:33:45.000
1 2016-03-21 12:33:50.000 EV-1
1 2016-03-21 12:33:55.000 EV-2 2016-03-21 12:40:20.000
1 2016-03-21 12:35:15.000 EV-3 2016-03-21 12:40:20.000
1 2016-03-21 12:35:15.000 EV-4 2016-03-21 12:40:20.000
1 2016-03-21 12:40:20.000 EV-5 2016-03-21 12:40:20.000
2 2016-03-21 12:40:50.000 EV-1
2 2016-03-21 12:41:25.000 EV-2 2016-03-21 12:47:35.000
2 2016-03-21 12:41:25.000 EV-3 2016-03-21 12:47:35.000
2 2016-03-21 12:42:13.000 EV-4 2016-03-21 12:47:35.000
2 2016-03-21 12:47:35.000 EV-5 2016-03-21 12:47:35.000
我尝试了什么:
select d.ID, d.TIME, d.EVENT, max(dd.TIME) endTime
from dataTable d
inner join dataTable dd on d.ID = dd.ID and d.EVENT = dd.EVENT and d.TIME < dd.TIME
group by d.ID, d.TIME, d.EVENT
答案 0 :(得分:0)
简单解决方案,使用相关子选择返回大于或等于当前行时间的最小EV-5时间。 (对于除EV-1之外的所有事件,都有一个case
表达式。)
select t1.*, case when t1.event <> 'EV-1' then (select min(t2.TIME) from dataTable t2
where t2.event = 'EV-5'
and t2.TIME >= t1.time)
end as endTime
from dataTable t1
或者,如果可以使用id
,请执行自我(左)联接:
select t1.*, case when t1.event <> 'EV-1' then t2.TIME
end as endTime
from dataTable t1
left join dataTable t2 on t1.id = t2.id and t2.event = 'EV-5'
(left join
如果需要,还可以返回没有任何EV-5的ID。)
答案 1 :(得分:0)
@ jarhl的DBMS支持SQL Server 2014等窗口化聚合函数的逻辑:
SELECT t.*,
CASE
WHEN EVENT <> 'EV-1'
THEN MIN(CASE WHEN EVENT = 'EV-5' THEN TIME end)
OVER (PARTITION BY ID -- maybe not needed
ORDER BY TIME
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
END AA endTime
FROM tablename AS t1
答案 2 :(得分:0)
将ID列更正为实际ID,请尝试
IF (SELECT OBJECT_ID('tempdb..#Events')) IS NOT NULL
BEGIN
DROP TABLE #Events
END
CREATE TABLE #Events (ID INT,EventTime datetime, eventName varchar(4))
INSERT INTO #Events
VALUES
(1, '2016-03-21 12:30:00.000','EV-1'),
(1, '2016-03-21 12:30:30.000','EV-2'),
(1, '2016-03-21 12:33:00.000','EV-3'),
(1, '2016-03-21 12:33:00.000','EV-4'),
(1, '2016-03-21 12:33:45.000','EV-5'),
(2, '2016-03-21 12:33:50.000','EV-1'),
(2, '2016-03-21 12:33:55.000','EV-2'),
(2, '2016-03-21 12:35:15.000','EV-3'),
(2, '2016-03-21 12:35:15.000','EV-4'),
(2, '2016-03-21 12:40:20.000','EV-5'),
(3, '2016-03-21 12:40:50.000','EV-1'),
(3, '2016-03-21 12:41:25.000','EV-2'),
(3, '2016-03-21 12:41:25.000','EV-3'),
(3, '2016-03-21 12:42:13.000','EV-4'),
(3, '2016-03-21 12:47:35.000','EV-5')
;
WITH cteEvent AS
(
SELECT ID, EventTime AS startTime,en.endTime
FROM #Events e
CROSS APPLY (
SELECT EventName,EventTime AS endTime
FROM #Events e2
WHERE e2.ID = e.id AND CAST(RIGHT(e2.eventname,1) AS INT) = 5) as en
WHERE e.EventName = 'EV-1'
)
SELECT c.id,eventName,startTime,
CASE
WHEN eventName = 'EV-1'
THEN NULL
ELSE endTime
END AS endTime
FROM cteEvent c
LEFT JOIN #Events e ON c.id = e.id