通过窗口函数进行SQL Server状态更改查询:如何在状态* WITHIN *状态块中运行总时间?

时间:2018-04-26 19:13:26

标签: sql sql-server

我通过以下查询跟踪计算机及其在各种状态下花费的时间:

    select ks.CalendarId 
    , ks.machineid
    , ks.machinestateid
    , lead(ks.machinestateid) over (partition by ks.machineid, ks.calendarid order by ks.machinefmstatetime desc) prevstateid
    , ks.machinestatehistoryid
    , ks.machinefmstatetime
    , ks.StateTimeInSeconds
    , sum(ks.statetimeinseconds) over (partition by ks.machineid, ks.calendarid, ks.machinestateid order by ks.machinefmstatetime) StateTimeSecTotal
from [dbo].[MachineStateDailyDistributionFact] ks
where calendarid in (20180425)
    and ks.machineid in (38141)
order by ks.MachineFmStateTime

除了StateTimeSecTotal之外,这一切都很好。当一台机器回到之前某个时间的状态时,StateTimeSecTotal会从它停止的地方开始。我需要第二次计算"重新开始"。

例如,在下面的图片中,我需要突出显示的单元格为0,然后按原样继续计数。

enter image description here

如何将查询更改为总状态持续时间"重新开始"当处于一个不同的状态时间块"?

感谢任何提示, SFF

1 个答案:

答案 0 :(得分:1)

你有一个缺口和岛屿问题。以下是使用row_number()的解决方案:

select . . .,
       sum(ks.statetimeinseconds) over (partition by ks.machineid, ks.calendarid, ks.machinestateid order by ks.machinefmstatetime) StateTimeSecTotal
select . . .,
       sum(ks.statetimeinseconds) over (partition by ks.machineid, ks.calendarid, ks.machinestateid, seqnum_1-seqnum_2 order by ks.machinefmstatetime) StateTimeSecTotal

from (select ks.*,
             row_number() over (partition by ks.machineid, ks.calendarid order by ks.machinefmstatetime) as seqnum_1,
             row_number() over (partition by ks.machineid, ks.calendarid, ks.machinestateid order by ks.machinefmstatetime) as seqnum_2
      from [dbo].[MachineStateDailyDistributionFact] ks
      where calendarid in (20180425) and ks.machineid in (38141)
     ) ks
order by ks.MachineFmStateTime;

行号的不同标识了机器ID状态的相邻组。