Summenintervall der Daten in derselben Spalte


10

Wie summieren Sie die Unterschiede eines Datumsbereichs in derselben Spalte zwischen verschachtelten Zeilen am besten? Ich habe eine Datetime-Spalte und möchte die Differenz zwischen Zeilen berechnen. Ich möchte den Unterschied in Sekunden. Bei dieser Frage geht es nicht darum, wie ein Unterschied zwischen zwei Zeitstempeln ermittelt werden kann, sondern vielmehr darum, wie zwischen Zeilen in derselben Tabelle am effizientesten berechnet werden kann. In meinem Fall hat jede Zeile einen Datetime-Ereignistyp, der zwei Zeilen logisch miteinander verbindet.

Details Bezogen auf das Gruppieren der Ereignistypen von Start und Ende. (Andriy Ms Frage) Start und Ende "sollten" aufeinanderfolgend sein. Wenn ein Start kein nachfolgendes Ende hat, sollte er aus der Summe herausgelassen werden. Fahren Sie mit dem nächsten Start fort, um zu sehen, ob er ein Ende hat. Zur Summe der Gesamtsekunden sollten nur aufeinanderfolgende Start-End-Paare addiert werden.

Arbeiten in postgresql 9.x ...

Beispieldaten in Tabelle;

eventtype, eventdate
START, 2015-01-01 14:00
END, 2015-01-01 14:25
START, 2015-01-01 14:30
END, 2015-01-01 14:43
START, 2015-01-01 14:45
END, 2015-01-01 14:49
START, 2015-01-01 14:52
END, 2015-01-01 14:55

Hinweis: Alle Start- und Enddaten sind aufeinanderfolgend.

Hier ist mein erster Versuch. Scheint zu funktionieren.

SELECT 
-- starts.*
SUM(EXTRACT(EPOCH FROM (eventdate_next - eventdate))) AS duration_seconds
FROM
( 
    WITH x AS (
        SELECT *, dense_rank() OVER (ORDER BY eventdate) AS rnk
        FROM   table
        AND eventdate > '2015-01-01 00:00:00.00'
        AND eventdate < '2016-01-01 23:59:59.59' 
        )
    SELECT x.eventdate, x.eventtype, y.eventdate AS eventdate_next,  y.eventtype AS eventtype_next
    FROM   x
    LEFT   JOIN (SELECT DISTINCT eventdate, eventtype, rnk FROM x) y ON y.rnk = (x.rnk + 1)
    ORDER  BY x.eventdate
) starts
WHERE
eventtype = 'START'   
GROUP BY eventtype 

Mein erster Versuch basiert auf einem großartigen Beispiel aus Stackoverflow Postgres 9.1 - Den nächsten Wert ermitteln

Hinweis; Sie können die GROUP BY und die SUM kommentieren und die Starts * auskommentieren, um einen Datensatz für jede einzelne Dauer in der Summe zu erhalten.

Antworten:


10

Mit der LEADAnalysefunktion können Sie die Daten der nächsten Zeile eventtypeund eventdateder aktuellen Zeile abrufen:

SELECT
  eventtype,
  eventdate,
  LEAD(eventtype) OVER (ORDER BY eventdate) AS nexttype,
  LEAD(eventdate) OVER (ORDER BY eventdate) AS nextdate
FROM
  atable
WHERE
      eventdate >= '2015-01-01 00:00:00.00'
  AND eventdate <  '2016-01-01 23:59:59.59'

Wenn Sie die obige Abfrage als abgeleitete Tabelle verwenden, können Sie die Ausgabe weiter filtern eventtype = 'START' AND nexttype = 'END'und die Differenzsumme erhalten:

SELECT
  SUM(EXTRACT(EPOCH FROM (nextdate - eventdate))) AS duration_seconds
FROM
  (
    SELECT
      eventtype,
      eventdate,
      LEAD(eventtype) OVER (ORDER BY eventdate) AS nexttype,
      LEAD(eventdate) OVER (ORDER BY eventdate) AS nextdate
    FROM
      atable
    WHERE
          eventdate >= '2015-01-01 00:00:00.00'
      AND eventdate <  '2016-01-01 23:59:59.59'
  ) AS s
WHERE
      eventtype = 'START'
  AND nexttype  = 'END'
;

Als geringfügige Abweichung können Sie die Unterabfrage als CTE implementieren:

WITH cte AS
  (
    SELECT
      eventtype,
      eventdate,
      LEAD(eventtype) OVER (ORDER BY eventdate) AS nexttype,
      LEAD(eventdate) OVER (ORDER BY eventdate) AS nextdate
    FROM
      atable
    WHERE
          eventdate >= '2015-01-01 00:00:00.00'
      AND eventdate <  '2016-01-01 23:59:59.59'
  )
SELECT
  SUM(EXTRACT(EPOCH FROM (nextdate - eventdate))) AS duration_seconds
FROM
  cte
WHERE
      eventtype = 'START'
  AND nexttype  = 'END'
;

Dieses Umschreiben kann Auswirkungen auf die Leistung haben, da im Gegensatz zu einer abgeleiteten Tabelle ein CTE in PostgreSQL materialisiert wird. Tests sollten ergeben, ob es einen Unterschied gibt und wenn ja, welche Option für Sie besser ist.


Andriy, danke! Ich werde die CTE-Version ausprobieren und sehen, wie es hilft.
C Smith
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.