SQL - 基于另一列的开始和结束日期

时间:2017-02-27 13:47:54

标签: sql sql-server

简化结构。

我需要操作类型为4且操作类型为1的记录之间的两个日期。

记录可能会多次处于该状态,我需要单独的行进行

例如,对于IncidentId = 1

  • 第1行 - StartTime = 2017-01-01 14:00(id:3) - 结束时间= 2017-01-01 20:00(id:5)
  • 第2行 - StartTime = 2017-01-01 21:00(id:6) - 结束时间= 2017-01-02 11:00(id:9)

    CREATE TABLE #returntable 
      ( 
         [incidentid] INT, 
         [starttime]  DATETIME, 
         [endtime]    DATETIME 
      ) 

    CREATE TABLE #testtableofdoom 
      ( 
         [incidentlogid] INT, 
         [incidentid]    INT, 
         [timestamp]     DATETIME, 
         [actiontypeid]  INT 
      ) 

     INSERT INTO #testtableofdoom
            ( incidentlogid, incidentid, timestamp, actiontypeid )
     VALUES ( 1, 1, '2017-01-01 09:00', 1 )
        ,   ( 2, 1, '2017-01-01 11:00', 1 )
        ,   ( 3, 1, '2017-01-01 14:00', 4 )
        ,   ( 4, 1, '2017-01-01 16:00', 4 )
        ,   ( 5, 1, '2017-01-01 20:00', 1 )
        ,   ( 6, 1, '2017-01-01 21:00', 4 )
        ,   ( 7, 1, '2017-01-02 09:00', 4 )
        ,   ( 8, 2, '2017-01-02 10:00', 1 )
        ,   ( 9, 1, '2017-01-02 11:00', 1 )
        ,   ( 10, 1, '2017-01-02 14:00', 1 )
        ,   ( 11, 2, '2017-01-02 15:00', 4 )
        ,   ( 12, 1, '2017-01-02 16:00', 1 )    
        ,   ( 13, 1, '2017-01-02 17:00', 1 )
        ,   ( 14, 1, '2017-01-02 18:00', 1 )
        ,   ( 15, 2, '2017-01-02 15:00', 1 );

    DROP TABLE #testtableofdoom 

    DROP TABLE #returntable 

2 个答案:

答案 0 :(得分:2)

我使用了表变量而不是临时表,并且使用了比你更短的列名,但这样做有效:

 startLogid  endLogId    iID  startTime               endTime
 ----------- ----------- ---- ----------------   ----------------
     3           5        1   2017-01-01 14:00   2017-01-01 20:00
     6           9        1   2017-01-01 21:00   2017-01-02 11:00
    11          15        2   2017-01-02 15:00   2017-01-02 15:00

这会产生以下结果:

s

它使用自联接。 e表示actionType 4的第一个(开始)记录,logId表示操作类型为1的结束记录。由于logId递增,结束记录必须高于logId起始记录,它必须比具有相同iIdatId = 1的起始记录高Select s.iID, s.dt startTime, e.dt endTime from @tt s join @tt e on e.logId = (Select min(logId) from @tt -- lowest log greater than start logId where iId = s.iID -- same iId and atId = 1 -- with atId = 1 and logId > s.logId) -- greater than start logId

where s.aTid = 4 
      and ((Select atId from @tt            -- atId of immed prior = 1
            Where logId = 
               (Select Max(logId) from @tt
                where logId < s.LogId 
                 and iId = s.iId)) = 1
        or Not Exists                       -- or there is no prior record
           (Select * from @tt
            Where logId < s.LogId 
              and iId = s.iID))  

最后,开始记录必须限制在那些之前没有其他相同事件记录或紧接其之前有“1”记录的“4”记录。

{{1}}

答案 1 :(得分:1)

这样的事情?

select 
d.[timestamp] as StartDate, 
(select top 1 [timestamp] 
 from #testTableOfDoom d2 
 where d2.incidentid = 1 and d2.[timestamp] > d.[timestamp] and actiontypeid = 1 
 order by d2.[timestamp] asc
) as EndDate
from
    (select 
    p.[timestamp],
    LAG(p.actiontypeid) OVER (ORDER BY incidentlogid asc) PrevValue,
    p.actiontypeid 
    from #testTableOfDoom p
    where p.incidentid = 1) d
where d.actiontypeid = 4 
and d.PrevValue <> 4