我有一个包含以下列的表格x
Message TimeEvent TriggerValue TimeStamp
m1 t1 1 2017-10-18 13:28:43.993
m1 t1 1 2017-10-18 13:28:53.787
m1 t1 1 2017-10-18 13:29:53.787
0 2017-10-18 13:30:53.787
如果我想在TriggerValue为1时找到时间的持续时间(当触发值为0和t1时TimeStamp之间的时间差),我该怎么办...就像我必须返回
m1 t1 duration
当我在第3行时,如果第4行Triggervalue为0,那么我减去TimeStamp和t1。我觉得我需要使用LEAD功能,但不知道如何在where子句中使用它。
任何想法都将不胜感激。
答案 0 :(得分:3)
您的要求有点模糊,DDL,样本数据和所需的输出使我们更容易为您提供帮助。有关详细信息,请查看此article。
要获得持续时间,我们需要一个开始和结束日期,我们需要能够按某种方式进行分组。对于我下面的解决方案,我将按消息分组。持续时间我会假设你正在寻找秒;如果没有,它将很容易调整。
LEAD(& LAG)对您没有帮助,因为他们使用静态值来说明前进或后退的行数。例如。 LAG(col1, 1)
说“前一行”或LEAD(col1,5)说“前五行”。但是,你不能说,“给我下一行的值是”x“。注意这个例子:
declare @table table (someNbr int);
insert @table(someNbr) values (5),(10),(12),(15),(20);
select
someNbr,
PreviousRow = LAG(someNbr,1) over (order by someNbr),
twoRowsBack = LAG(someNbr,2) over (order by someNbr),
[ |] = '|',
someNbr,
nextRow = LEAD(someNbr,1) over (order by someNbr),
twoRowsAhead = LEAD(someNbr,2) over (order by someNbr)
from @table;
<强>结果:
someNbr PreviousRow twoRowsBack | someNbr nextRow twoRowsAhead
----------- ----------- ----------- ---- ----------- ----------- ------------
5 NULL NULL | 5 10 12
10 5 NULL | 10 12 15
12 10 5 | 12 15 20
15 12 10 | 15 20 NULL
20 15 12 | 20 NULL NULL
您正在寻找的内容可以通过简单的分组或分区来处理。这是我放在一起的东西:
示例数据
if object_id('tempdb..#x') is not null drop table #x;
select * into #x
from (values
('m2', 't1', 1, '2017-10-18 11:26:43.222'),
('m2', 't1', 1, '2017-10-18 11:28:52.780'),
('m2', 't1', 1, '2017-10-18 11:29:53.709'),
('m2', 't1', 0, '2017-10-18 11:31:53.781'),
('m1', 't1', 1, '2017-10-18 13:28:43.993'),
('m1', 't1', 1, '2017-10-18 13:28:53.787'),
('m1', 't1', 1, '2017-10-18 13:29:53.787'),
('m1', 't1', 0, '2017-10-18 13:30:53.787'))
v([Message], [TimeEvent], TriggerValue, [TimeStamp]);
create clustered index uq_cl_x on #x([Message], [TimeStamp]);
我的解决方案
select [Message], [TimeEvent], Duration = datediff(second, minTime, maxTime)
from
(
select [Message], [TimeEvent],
rn = row_number() over (partition by [message] order by [timestamp]),
minTime = min(timeStamp) over (partition by [message] order by [timeStamp]),
maxTime = max(case TriggerValue when 0 then [timestamp] end) over (partition by [Message] order by (select 1))
from #x
) x
where rn=1;
<强>结果
Message TimeEvent Duration
------- --------- -----------
m1 t1 130
m2 t1 310
有几点需要注意:
1.我正在使用ROW_NUMBER来获取不同的值,而不需要在执行计划中进行排序(更好的性能)。我可以通过删除row_number逻辑并使用DISTINCT来获得相同的结果,但它会更慢。
2.我的窗口子句中有ORDER BY语句(例如minTime = min(timeStamp) over (partition by [message] order by [timeStamp])
);这些不是必需的,但也会提高性能。
答案 1 :(得分:-1)
只要Timestamp列具有Datetime数据类型,您就可以相互减去它们。你将需要一种方法来识别你减去Triggervalue为1的三个时间戳中的哪一个,所以我为这个例子设置了ID = 3。
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>15165</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:15165/</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>