SQL-基于另一列的开始和结束日期
简化结构 我需要动作类型为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:9SQL-基于另一列的开始和结束日期,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
我使用了表变量而不是临时表,并且列名比您短,但这是可行的:
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