T-SQL从单个列开始和结束日期时间
我有一张不同资产的开/关事件表。我需要在不使用光标的情况下获取开始和停止事件时间的列表 资料来源:T-SQL从单个列开始和结束日期时间,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一张不同资产的开/关事件表。我需要在不使用光标的情况下获取开始和停止事件时间的列表 资料来源: Item EventDate Event A 2011-10-03 00:01:00 On B 2011-10-03 00:01:00 On A 2011-10-03 00:02:00 Off C 2011-10-03 00:01:00 On B 2
Item EventDate Event
A 2011-10-03 00:01:00 On
B 2011-10-03 00:01:00 On
A 2011-10-03 00:02:00 Off
C 2011-10-03 00:01:00 On
B 2011-10-03 00:02:00 Off
A 2011-10-03 00:02:02 On
C 2011-10-03 00:02:05 On
A 2011-10-03 00:02:07 Off
预期结果:
Item Start End
A 2011-10-03 00:01:00 2011-10-03 00:02:00
A 2011-10-03 00:02:02 2011-10-03 00:02:07
B 2011-10-03 00:01:00 2011-10-03 00:01:00
C 2011-10-03 00:01:00 2011-10-03 00:02:05
这是一个解决方案,有概念证明供大家验证 我注意到
C
的Off
事件被标记为新的On
。我解决了这个问题,但这也导致我编写了一个解决方案,允许有一个已经开始但尚未完成的事件,因此我包含了一个开放式事件D
此外,我的解决方案适用于重叠时段
declare @YourTable table (Item varchar(10),
EventDate datetime,
Event varchar(10))
insert into @YourTable values
('A', '2011-10-03 00:01:00', 'On'),
('B', '2011-10-03 00:01:00', 'On'),
('A', '2011-10-03 00:02:00', 'Off'),
('C', '2011-10-03 00:01:00', 'On'),
('B', '2011-10-03 00:02:00', 'Off'),
('A', '2011-10-03 00:02:02', 'On'),
('C', '2011-10-03 00:02:05', 'Off'),
('A', '2011-10-03 00:02:07', 'Off'),
('D', '2011-10-03 00:02:02', 'On')
select tOn.Item, tOn.EventDate Start, tOff.EventDate [End]
from (
select Item, EventDate,
ROW_NUMBER() Over(Partition by Item order by EventDate) EventID
from @YourTable where Event = 'On'
) tOn
LEFT JOIN (
select Item, EventDate,
ROW_NUMBER() Over(Partition by Item order by EventDate) EventID
from @YourTable where Event = 'Off'
) tOff
on (tOn.Item = tOff.Item and tOn.EventID = tOff.EventID)
解释
我们将数据集分为两部分:打开
事件和关闭
事件。每个包含一个编号的行,当项更改时重新启动
基本上,我们有一种先进先出的方法:打开的第一个将被关闭的第一个关闭的关闭,因此,基于这种方法,此查询将支持重叠时段。因此A
的每个On
事件都将有其事件ID
,该ID将链接到相应的Off
事件ID
未测试的左联接将支持开放式期间
;WITH myCTE AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY Item ORDER BY EventDate) AS rn
FROM MyTable
)
SELECT
M1.Item,
M1.EventDate AS Start,
M2.EventDate AS End
FROM
myCTE M1
JOIN
myCTE M2 ON M1.Item = M2.Item AND M1.rn+1 = M2.rn
WHERE
M1.Event = 'On'
AND
M2.Event = 'Off';
你会有一个项目的重叠周期吗?尝试过子查询和cte,但运气不太好。这应该很简单。我真的想把它保存在服务器上。这里几乎解决了同样的问题,只需稍加操作,你就可以像我在Survestion(我使用了@Adrian的数据)中所做的那样使用聚合函数minimum和maximum。看看我的解决方案,看看你有多喜欢它。它支持重叠期和开放期,实际上,C的数据是故意的。可以记录多个关闭和关闭。我仍然在寻找一个很好的方法来清除这些。根据期望输出中的最后一行:C 2011-10-03 00:01:00 2011-10-03 00:02:05
,它看起来不是故意的。不管怎样,我很乐意帮忙。
declare @YourTable table (Item varchar(10), EventDate datetime, Event varchar(10))
insert into @YourTable values
('A','2011-10-03 00:01:00''On'),
('B','2011-10-03 00:01:00','On'),
('A','2011-10-03 00:02:00','Off'),
('C','2011-10-03 00:01:00','On'),
('B','2011-10-03 00:02:00','Off'),
('A','2011-10-03 00:02:02','On'),
('C','2011-10-03 00:02:05','Off'),
('A','2011-10-03 00:02:07','Off'),
('D','2011-10-03 00:02:02','On')
;with a as
(
select item, eventdate, event, ROW_NUMBER() Over(Partition by Item order by EventDate) RN
from @YourTable
),
b as (
select item, eventdate, 0 e, rn, event from a where rn = 1
union all
select b.item, a.eventdate, case when b.event = 'Off' then b.e+1 else b.e end, a.rn, a.event
from b
join a on b.rn + 1 = a.rn and a.item = b.item
)
select item, min(eventdate) Start, max(eventdate) [End]
from b
group by item, e
order by item, e