2017-03-24 4 views
1

Ich versuche, gleitende Durchschnitte über festgelegte Zeiträume zu generieren, die nach einer Artikel-ID-Spalte gruppiert sind.PostgreSQL Grouped Rolling Averages

Hier ist das grundlegende Layout der Tabelle und einige Dummy-Daten, mit der Flaum gezupft:

---------------------------------------------------- 
| id | itemid | isup | logged    | 
---------------------------------------------------- 
| 1 | 1  | true | 2017-03-23 12:55:00 | 
| 2 | 1  | false | 2017-03-23 12:57:00 | 
| 3 | 1  | true | 2017-03-23 13:07:00 | 
| 4 | 1  | false | 2017-03-23 13:09:00 | 
| 5 | 1  | true | 2017-03-23 13:50:00 | 
| 6 | 2  | false | 2017-03-23 12:55:00 | 
| 7 | 2  | true | 2017-03-23 14:00:00 | 
| 8 | 2  | false | 2017-03-23 14:03:00 | 
---------------------------------------------------- 

ich eine answer to a previous question on rolling averages gefunden, aber ich kann nicht ganz scheinen, wie zu einer Gruppe durch die die Mittelwerte, um herauszufinden, Artikel Identifikationsnummer; so ziemlich alle Wege, die ich hinuntergegangen bin, sind mit der Statistik ausgegangen, die völlig falsch ist.

Hier ist mein Ausgangspunkt - ich habe das Gefühl, dass mein Mangel an Verständnis von ROW_NUMBER() OVER nicht hilft.

SELECT id, itemid, AVG(isup) 
    OVER (PARTITION BY groupnr ORDER BY logged) AS averagehour 
FROM (  
    SELECT id, itemid, isup, logged, intervalgroup, 
     itemid - ROW_NUMBER() OVER (
      partition by intervalgroup ORDER BY logged) AS groupnr 
    FROM (
     SELECT id, itemid, logged, 
      CASE WHEN isup = TRUE THEN 1 ELSE 0 END AS isup, 
      'epoch'::TIMESTAMP + '3600 seconds'::INTERVAL * 
       (EXTRACT(EPOCH FROM logged)::INT4/3600) AS intervalgroup 
     FROM uplog 
) alias_inner 
) alias_outer 
ORDER BY logged; 

Jede Hilfe würde sehr geschätzt werden.

+4

"Gruppierte Rollendurchschnitte" ist sehr allgemein. Bitte beschreiben Sie, was Sie versuchen zu tun. Beispieldaten und gewünschte Ergebnisse helfen. –

Antwort

0

Die verknüpfte Antwort enthält fast alles, was Sie brauchen. Wenn Sie weiter „Gruppe“ wollen (zb durch itemid), werden Sie nur brauchen, um diese „Gruppen“ auf die PARTITION BY Klauseln der Fensterfunktionen hinzuzufügen:

select *, avg(isup::int) over (partition by itemid, group_nr order by logged) as rolling_avg 
from  (
    select *, id - row_number() over (partition by itemid, interval_group order by logged) as group_nr 
    from (
     select *, 'epoch'::timestamp + '3600 seconds'::interval * (extract(epoch from logged)::int4/3600) as interval_group 
     from dummy 
    ) t1 
) t2 
order by itemid, logged 

Hinweis jedoch, dass diese (und die verknüpfte Antwort) funktioniert nur, weil id keine Lücken hat & ist in Ordnung mit dem Zeitstempelfeld seiner Tabelle. Wenn das nicht der Fall ist, müssen Sie

row_number() over (partition by itemid order by logged) - row_number() over (partition by itemid, interval_group order by logged) as group_nr 

statt id - row_number() ....

http://rextester.com/YBSC43615

Auch, wenn Sie stündlich Gruppen verwenden werden, können Sie verwenden:

date_trunc('hour', logged) as interval_group 

anstelle der allgemeineren Arithmetik (wie @LaurenzAlbe schon bemerkt).

+0

Ah, ich hatte nicht gewusst, dass Sie mehrere Einträge in der Partition haben könnten! – GMemory

0

Meine Antwort geht davon aus

  1. dass logged ein timestamp with time zone ist, die der einzige vernünftige Datentyp für die Protokollierung ist.

  2. dass Ihre komplizierte Datumsarithmetik den Wert logged zur Zeitzone UTC berechnen soll (sonst würden Sie 'epoch'::timestamp als Basis verwenden?), Auf die nächstniedrigere Stunde gerundet.

  3. , die Sie nach diesem gerundeten Zeitstempel und itemid gruppieren möchten.

Hier wäre eine Antwort sein:

SELECT *, 
     avg(isup::integer) 
      OVER (PARTITION BY itemid, 
          date_trunc('hour', logged AT TIME ZONE 'UTC') 
       ) average, 
     date_trunc('hour', logged AT TIME ZONE 'UTC') avg_interval 
FROM uplog 
ORDER BY logged; 

┌────┬────────┬──────┬────────────────────────┬────────────────────────┬─────────────────────┐ 
│ id │ itemid │ isup │   logged   │  average   │ avg_interval  │ 
├────┼────────┼──────┼────────────────────────┼────────────────────────┼─────────────────────┤ 
│ 6 │  2 │ f │ 2017-03-23 12:55:00+01 │ 0.00000000000000000000 │ 2017-03-23 11:00:00 │ 
│ 1 │  1 │ t │ 2017-03-23 12:55:00+01 │ 0.50000000000000000000 │ 2017-03-23 11:00:00 │ 
│ 2 │  1 │ f │ 2017-03-23 12:57:00+01 │ 0.50000000000000000000 │ 2017-03-23 11:00:00 │ 
│ 3 │  1 │ t │ 2017-03-23 13:07:00+01 │ 0.66666666666666666667 │ 2017-03-23 12:00:00 │ 
│ 4 │  1 │ f │ 2017-03-23 13:09:00+01 │ 0.66666666666666666667 │ 2017-03-23 12:00:00 │ 
│ 5 │  1 │ t │ 2017-03-23 13:50:00+01 │ 0.66666666666666666667 │ 2017-03-23 12:00:00 │ 
│ 7 │  1 │ t │ 2017-03-23 14:00:00+01 │ 0.50000000000000000000 │ 2017-03-23 13:00:00 │ 
│ 8 │  1 │ f │ 2017-03-23 14:03:00+01 │ 0.50000000000000000000 │ 2017-03-23 13:00:00 │ 
└────┴────────┴──────┴────────────────────────┴────────────────────────┴─────────────────────┘ 
(8 rows)