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

SQL-基于另一列的开始和结束日期,sql,sql-server,Sql,Sql Server,简化结构 我需要动作类型为4和动作类型为1的记录之间的两个日期 该记录可能多次处于该状态,我需要为它们的时间设置单独的行 例如IncidentId=1 第1行-开始时间=2017-01-01 14:00 id:3-结束时间=2017-01-01 20:00 id:5 第2行-开始时间=2017-01-01 21:00 id:6-结束时间=2017-01-02 11:00 id:9 我使用了表变量而不是临时表,并且列名比您短,但这是可行的: declare @tt TABLE ( lo

简化结构

我需要动作类型为4和动作类型为1的记录之间的两个日期

该记录可能多次处于该状态,我需要为它们的时间设置单独的行

例如IncidentId=1

第1行-开始时间=2017-01-01 14:00 id:3-结束时间=2017-01-01 20:00 id:5 第2行-开始时间=2017-01-01 21:00 id:6-结束时间=2017-01-02 11:00 id:9
我使用了表变量而不是临时表,并且列名比您短,但这是可行的:

declare @tt TABLE ( 
     logId INT, iId INT, 
     dt DATETIME, atId  INT  

INSERT @tt (logId, iId, 
    dt, atId) 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)

Select s.logId startLogid, e.logId endLogId, 
       s.iID, s.dt startTime, e.dt endTime 
from @tt s join @tt e
    on e.logId = 
       (Select min(logId) from @tt
        where iId = s.iID
            and atId = 1
            and logId > s.logId)                
where s.aTid = 4 
      and ((Select atId from @tt
            Where logId = 
               (Select Max(logId) from @tt
                where logId < s.LogId 
                 and iId = s.iId)) = 1
        or Not Exists 
           (Select * from @tt
            Where logId < s.LogId 
              and iId = s.iID))    
它使用自联接。s表示actionType为4的第一个开始记录,e表示actionType为1的结束记录。由于logId递增,因此结束记录的logId必须高于开始记录,并且它必须是比具有相同iId且atId=1的开始记录高的最低logId

最后,开始记录必须限于之前没有其他相同事件记录或之前有1条记录的4条记录

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))  
像这样的

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

你怎么知道哪一个开始时间4和哪一个结束时间1?例如:IncidentLogid 6和7都表示IncidentLogid 1的开始。您如何知道IncidentLogID 8是否与6或7配对?这是数据的格式。当事件处于搁置状态时,它将保持ActionTypeId为4。它一直保持这样,直到它不再保持不变,但是其他字段可以在不改变4的情况下改变。中间的记录,例如行id 7,在返回值时可以忽略。恐怕没有运气,它会为事件1获取第一个记录实例,但不会为第二个记录获取。总的来说,查询应该返回三行而不是两行。事件1在第6行至第8行以及第3行至第5行再次处于保留状态。干杯,但第8行表示incidentId=2。从第11行到第15行的第2个事件呢?第1个事件在第6行重新暂停,然后在第9行取消暂停。打字错误下面的查询返回所需的信息-在光标内时。理想情况下,我不希望有一个光标,但如果这是需要的,我会沿着这条路线走。
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))  
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