2016-06-20 10 views
0

Ich habe eine Reihe von Daten jede Minute gesammelt und in einer Postgres-Datenbank gespeichert. Ich versuche eine Abfrage zu erstellen, die den Unterschied im Wert über diesen Zeitraum von 5 Minuten anzeigt.PostgreSQL Unterschied über den Zeitraum

Also, wo ich die folgenden Daten:

val   created_at   
115414.568 2016-06-18 18:29:53 
115443.656 2016-06-18 18:30:53 
115461.817 2016-06-18 18:31:53 
115494.406 2016-06-18 18:32:53 
115527.151 2016-06-18 18:33:53 
115550.096 2016-06-18 18:34:53 
115610.065 2016-06-18 18:35:53 
115640.957 2016-06-18 18:36:53 
115667.033 2016-06-18 18:37:53 
115683.302 2016-06-18 18:38:53 
115727.717 2016-06-18 18:39:53 
115748.331 2016-06-18 18:40:53 
115763.520 2016-06-18 18:41:53 
115795.607 2016-06-18 18:42:53 
115849.592 2016-06-18 18:43:53 
115871.538 2016-06-18 18:44:53 
115908.999 2016-06-18 18:45:53 
115923.776 2016-06-18 18:46:53 
115961.043 2016-06-18 18:47:53 
115988.369 2016-06-18 18:48:53 
116003.320 2016-06-18 18:49:53 
116056.299 2016-06-18 18:50:53 
116069.396 2016-06-18 18:51:53 
116092.485 2016-06-18 18:52:53 
116137.878 2016-06-18 18:53:53 
116162.937 2016-06-18 18:54:53 
116204.077 2016-06-18 18:55:53 
116235.593 2016-06-18 18:56:53 
116242.502 2016-06-18 18:57:53 
116285.713 2016-06-18 18:58:53 
116317.299 2016-06-18 18:59:53 
116340.120 2016-06-18 19:00:53 
116387.000 2016-06-18 19:01:53 

Ich möchte folgende Gruppierung:

2016-06-18 18:25:00 ... 
2016-06-18 18:30:00 166.409 
2016-06-18 18:35:00 138.266 
2016-06-18 18:40:00 160.668 
2016-06-18 18:45:00 147.300 
2016-06-18 18:50:00 147.778 
2016-06-18 18:55:00 136.043 
2016-06-18 19:00:00 ... 

Ich habe es geschafft, das folgende Stück zusammen:

SELECT 
    val, 
    first_value(val) over (partition by period_start) as first_value, 
    period_start, 
    created_at 
FROM (
    SELECT 
    date_trunc('minute', created_at) - (EXTRACT(MINUTE FROM created_at)::INTEGER % 5) * INTERVAL '1 minute' AS period_start, 
    concat(kwh, '.', LPAD(wh::text, 3, '0'))::FLOAT as val, 
    "readings"."created_at" 
    FROM 
    readings 
    WHERE 
    "readings"."created_at" between '2016-06-18 18:29:53' AND '2016-06-18 19:02:53' 
) s1 

Was mir folgendes gibt:

val   first_value period_start  created_at 
115414.568 115414.568 2016-06-18 18:25:00 2016-06-18 18:29:53.121609 
115443.656 115443.656 2016-06-18 18:30:00 2016-06-18 18:30:53.124389 
115461.817 115443.656 2016-06-18 18:30:00 2016-06-18 18:31:53.127074 
115494.406 115443.656 2016-06-18 18:30:00 2016-06-18 18:32:53.129728 
115527.151 115443.656 2016-06-18 18:30:00 2016-06-18 18:33:53.1324 
115550.096 115443.656 2016-06-18 18:30:00 2016-06-18 18:34:53.135078 
115610.065 115610.065 2016-06-18 18:35:00 2016-06-18 18:35:53.137708 
115640.957 115610.065 2016-06-18 18:35:00 2016-06-18 18:36:53.140347 
115667.033 115610.065 2016-06-18 18:35:00 2016-06-18 18:37:53.143023 
115683.302 115610.065 2016-06-18 18:35:00 2016-06-18 18:38:53.145754 
115727.717 115610.065 2016-06-18 18:35:00 2016-06-18 18:39:53.14852 
115748.331 115748.331 2016-06-18 18:40:00 2016-06-18 18:40:53.151326 
115763.520 115748.331 2016-06-18 18:40:00 2016-06-18 18:41:53.154003 
115795.607 115748.331 2016-06-18 18:40:00 2016-06-18 18:42:53.156723 
115849.592 115748.331 2016-06-18 18:40:00 2016-06-18 18:43:53.159454 
115871.538 115748.331 2016-06-18 18:40:00 2016-06-18 18:44:53.162127 
115908.999 115908.999 2016-06-18 18:45:00 2016-06-18 18:45:53.164743 
115923.776 115908.999 2016-06-18 18:45:00 2016-06-18 18:46:53.167401 
115961.043 115908.999 2016-06-18 18:45:00 2016-06-18 18:47:53.169997 
115988.369 115908.999 2016-06-18 18:45:00 2016-06-18 18:48:53.17265 
116003.320 115908.999 2016-06-18 18:45:00 2016-06-18 18:49:53.175299 
116056.299 116056.299 2016-06-18 18:50:00 2016-06-18 18:50:53.17797 
116069.396 116056.299 2016-06-18 18:50:00 2016-06-18 18:51:53.180955 
116092.485 116056.299 2016-06-18 18:50:00 2016-06-18 18:52:53.183606 
116137.878 116056.299 2016-06-18 18:50:00 2016-06-18 18:53:53.186317 
116162.937 116056.299 2016-06-18 18:50:00 2016-06-18 18:54:53.189088 
116204.077 116204.077 2016-06-18 18:55:00 2016-06-18 18:55:53.191821 
116235.593 116204.077 2016-06-18 18:55:00 2016-06-18 18:56:53.194513 
116242.502 116204.077 2016-06-18 18:55:00 2016-06-18 18:57:53.197222 
116285.713 116204.077 2016-06-18 18:55:00 2016-06-18 18:58:53.199996 
116317.299 116204.077 2016-06-18 18:55:00 2016-06-18 18:59:53.208784 
116340.120 116340.120 2016-06-18 19:00:00 2016-06-18 19:00:53.217547 
116387.000 116340.120 2016-06-18 19:00:00 2016-06-18 19:01:53.226262 

Also ich denke, der nächste Schritt wäre, den ersten 2016.06.16 18:30:00 Wert vom ersten 2016-06-18 18:35:00 abzuziehen, aber ich bin mir nicht sicher, wie mach das (vielleicht mit der Window-Funktion) - es sei denn, es gibt einen einfacheren Weg, den ich übersehe?

Alle Tipps geschätzt.

+0

deutliche hinzufügen und entfernen Spalten '' created_at' nad val' –

+0

bitte SELECT first_value (val) über (partition by period_start) als first_value, period_start' –

+0

und dann 'select first_value, lag (erster_wert) over (partition by period_start) von (SELECT first_value (val) über (partition by period_start) als first_value, period_start –

Antwort

0

Eigentlich war dies weniger kompliziert als erwartet.

ich weiß schon, wie viele Minuten in einen Zeitraum von 15 Minuten jeder Lesung ist, so habe ich nur eine WHERE-Klausel alle Zeilen zu finden, wo dieser Wert 0.

Von dort aus ist, kann ich nur die LAG-Funktion des vorherigen Wert abziehen und erhält die Differenz

SELECT 
    val - (lag(val) over (order by created_at)) as diff, 
    val, 
    created_at 
FROM (
    SELECT 
    EXTRACT(MINUTE FROM created_at)::INTEGER % 5 as minutes_into_period, 
    concat(val, '.', LPAD(wh::text, 3, '0'))::FLOAT as val, 
    "readings"."created_at" 
    FROM 
    readings 
    WHERE 
    "readings"."created_at" between '2016-06-18 18:29:53' AND '2016-06-18 19:02:53' 
) s1 
WHERE minutes_into_period = 0 

mir gibt

diff    val   created_at 
        115443.656 2016-06-18 18:30:53.124389 
166.409   115610.065 2016-06-18 18:35:53.137708 
138.266000000003 115748.331 2016-06-18 18:40:53.151326 
160.667999999991 115908.999 2016-06-18 18:45:53.164743 
147.300000000003 116056.299 2016-06-18 18:50:53.17797 
147.778000000006 116204.077 2016-06-18 18:55:53.191821 
136.042999999991 116340.12 2016-06-18 19:00:53.217547 
0

Dies könnte ein Problem der Resampling/Interpolation gesehen werden. Sie möchten alle 5 Minuten einen Wert haben, damit Sie nur einen Unterschied zwischen den Zeilen mit der Fensterfunktion machen können.

Resampling und Interpolation ist ein relativ häufiges "Data Science" -Problem, das in PostGres nur schwer zu lösen ist. This great articles bietet eine Menge Antworten auf dieses Problem. Große Ideen sind:

  • generate_series
  • linear_interpolate
  • Fensterfunktionen
Verwandte Themen