简体   繁体   English

查询以获取每个组的最大时间

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM