2017-07-25 2 views
-2

below is the sample dataSQL-Abfrage benötigen Zeitdifferenz zu erhalten, basierend auf Status

Ich brauche Gesamtzeit, wenn Ebstatus und dgstatusON ist und bis zum nächsten DgStatus ist OFF.

Zum Beispiel, wenn wir unten Daten berücksichtigen:

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 

Hier insgesamt ON-Zeit beträgt 2 Stunden (3 bis 4 -> 1 Stunde und auf noch bis 5, so Gesamteinschaltdauer Zeit beträgt 2 Stunden) und beide Status wieder bei 7 und Dgstatus OFF bei 9, also hier ist die gesamte ON-Zeit 2 Stunden.

Schließlich insgesamt ON beträgt 4 Stunden

Kann jemand Abfrage geben für SQL Server 2012?

+0

Markieren Sie Ihre Frage mit der Version von SQL Server, die Sie verwenden. –

+0

Haben Sie etwas versucht? – JFPicard

+0

@JFPicard, Nein, ich bin neu auf SQL. –

Antwort

0

Wenn Sie auf eine Zeile pro ON und OFF reduzieren könnten, dann würde die Aggregation das Problem lösen. Sie können das tun, den Unterschied von Zeilennummern-Methode:

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); 

Von diesem können Sie die Summen erhalten:

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

Vielen Dank. Wie erreicht man dasselbe im 2008 Server? –

0

LAG können Sie die vorherige Zeile überprüfen, so dass Sie für eine Änderung überprüfen in 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; 
Verwandte Themen