需要Sql查询才能根据状态获取时差

时间:2017-07-25 12:20:15

标签: sql sql-server

below is the sample data

我需要 Ebstatus dgstatus ON 的总时间,直到下一步 DgStatus OFF

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

+?

此处总开启时间为2小时(3至4 - > 1小时,它仍然开启至5,因此总开启时间为2小时)并且状态再次开启为7且 Dgstatus OFF为9,所以总开启时间为2小时。

最后总开启时间为4小时

有人可以为SQL Server 2012提供查询吗?

2 个答案:

答案 0 :(得分: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';

答案 1 :(得分: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;