[英]Query to get max time from a group by for each group
I have data in the following format and would like to output it in second format.我有以下格式的数据,并希望以第二种格式输出。 I've tried a self join on the data and group by on id, time and event but nothing I've tried seems to work correctly.
我已经尝试对数据进行自我连接,并根据 id、时间和事件分组,但我尝试过的任何内容似乎都无法正常工作。
The time at EV-2 is the starting time and the time at EV-5 is the ending time. EV-2 处的时间为开始时间,EV-5 处的时间为结束时间。 EV-5 time can be written as the end time for each EV-2 - EV-5 event.
EV-5 时间可以写为每个 EV-2 - EV-5 事件的结束时间。
Thanks for any guidance with this matter.感谢您对此事的任何指导。
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
What I've tried:我试过的:
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
Simple solution, use a correlated sub-select to return the smallest EV-5 time larger or equal to the current row's time.简单的解决方案,使用相关的子选择返回大于或等于当前行时间的最小 EV-5 时间。 (Have a
case
expression to do this for all events but EV-1.) (有一个
case
表达式来为除 EV-1 之外的所有事件执行此操作。)
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
Alternatively, if id
can be used, do a self (left) join:或者,如果可以使用
id
,则执行 self (left) join:
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
to also return id's without any EV-5, if needed.) (如果需要,
left join
也返回没有任何 EV-5 的 id。)
@jarhl's logic for DBMSes supporting Windowed Aggregate Functions like SQL Server 2014: @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
Correcting your ID column to an actual ID, try将您的 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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.