2017-07-25 97 views
-2

below is the sample data需要SQL查询来获取时间差基于状态

我需要的总时间时EbstatusdgstatusON,直到下次DgStatusOFF

例如,如果我们考虑以下数据:

Ebstatus | dgstatus | ReadTime 
    ON | ON | 16/07/2017 3:00:00 
    ON | ON | 16/07/2017 4:00:00 
    ON | OFF | 16/07/2017 5:00:00 
    ON | OFF | 16/07/2017 6:00:00 
    ON | ON | 16/07/2017 7:00:00 
    ON | OFF | 16/07/2017 9:00:00 

在这里总的导通时间为2小时(3至4 - > 1小时,它仍然为ON,直到5,从而总的导通时间为2小时),并两个状态再次打开在7和Dgstatus关闭在9,所以这里总开启时间是2小时。

最后得总时间为4小时

有人可以给查询的SQL Server 2012?

+0

用您正在使用的SQL Server版本标记您的问题。 –

+0

你尝试过什么吗? – JFPicard

+0

@JFPicard,其实我不是新来的sql。 –

回答

0

如果您可以将每个ONOFF减少为一行,则聚合可以解决问题。你可以做到这一点使用行号的方法的区别:

select ebstatus, dgstatus, 
     min(readtime) as min_rt, max(readtime) as max_rt 
from (select t.*, 
      row_number() over (partition by ebstatus order by readtime) as seqnum_d, 
      row_number() over (partition by ebstatus, dgstatus partition by readtime) as seqnum_sd 
     from t 
    ) t 
group by ebstatus, dgstatus, (seqnum_sd - seqnum_d); 

由此看来,你可以得到总计:

select sum(datediff(hour, min_rt, next_min_rt)) as on_hours 
from (select ebstatus, dgstatus, 
      min(readtime) as min_rt, max(readtime) as max_rt, 
      lead(min(readtime)) over (partition by ebstatus, dgstatus order by min(readtime)) as next_min_rt 
     from (select t.*, 
        row_number() over (partition by ebstatus order by readtime) as seqnum_d, 
        row_number() over (partition by ebstatus, dgstatus partition by readtime) as seqnum_sd 
      from t 
      ) t 
     group by ebstatus, dgstatus, (seqnum_sd - seqnum_d) 
    ) t 
where dgstatus = 'ON' and ebstatus = 'ON'; 
+0

非常感谢。2008年服务器如何实现同样的功能? –

0

LAG可以检查以前行,以便您可以检查的变化dgstatus v alue

SET DATEFORMAT DMY; 
DECLARE @Mytable table (Ebstatus varchar(2), dgstatus varchar(3), ReadTime smalldatetime) 

INSERT @Mytable VALUES 
    ('ON', 'ON ', '16/07/2017 3:00:00'), 
    ('ON', 'ON ', '16/07/2017 4:00:00'), 
    ('ON', 'OFF', '16/07/2017 5:00:00'), 
    ('ON', 'OFF', '16/07/2017 6:00:00'), 
    ('ON', 'ON ', '16/07/2017 7:00:00'), 
    ('ON', 'OFF', '16/07/2017 9:00:00'); 

SELECT 
    SUM(Hours) 
FROM 
    (
    SELECT 
     *, 
     Hours = CASE 
        WHEN 
         Ebstatus = 'ON' AND 
         dgstatus = 'OFF' AND --may be needed to ensure we only count OFF rows 
         LAG(dgstatus) OVER (ORDER BY ReadTime) <> dgstatus 
        THEN 
         DATEDIFF(HOUR, LAG(ReadTime) OVER (ORDER BY ReadTime), ReadTime) 
        ELSE 0 END 
    FROM 
     @Mytable 
    ) X;