PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Jak uzyskać wartości średnie dla interwałów czasowych w Postgresie

Projekt bazy danych

Póki możesz praca z oddzielną datą i czas kolumn, tak naprawdę nie ma przewagi nad pojedynczym znacznik czasu kolumna. Dostosowałbym:

ALTER TABLE tbl ADD column ts timestamp;
UPDATE tbl SET ts = date + time;  -- assuming actual date and time types
ALTER TABLE tbl DROP column date, DROP column time;

Jeśli data i godzina nie są aktualne data i czas typy danych, użyj to_timestamp() . Powiązane:

Zapytanie

Wtedy zapytanie jest nieco prostsze:

SELECT *
FROM  (
   SELECT sn, generate_series(min(ts), max(ts), interval '5 min') AS ts
   FROM   tbl
   WHERE  sn = '4as11111111'
   AND    ts >= '2018-01-01'
   AND    ts <  '2018-01-02'
   GROUP  BY 1
   ) grid
CROSS  JOIN LATERAL (
   SELECT round(avg(vin1), 2) AS vin1_av
        , round(avg(vin2), 2) AS vin2_av
        , round(avg(vin3), 2) AS vin3_av
   FROM   tbl
   WHERE  sn =  grid.sn
   AND    ts >= grid.ts
   AND    ts <  grid.ts + interval '5 min'
   ) avg;

db<>fiddle tutaj

Wygeneruj siatkę czasów rozpoczęcia w pierwszym podzapytaniu siatka , od pierwszego do ostatniego kwalifikującego się wiersz w podanym przedziale czasowym.

Połącz z wierszami znajdującymi się w każdej partycji za pomocą LATERAL dołącz i natychmiast agreguj średnie w podzapytaniu średnia . Ze względu na agregaty zawsze zwraca wiersz, nawet jeśli nie znaleziono żadnych wpisów. Średnie domyślnie to NULL w tym przypadku.

Wynik obejmuje wszystkie przedziały czasowe między pierwszym a ostatnim wierszem kwalifikującym w danym przedziale czasowym. Różne inne kompozycje wyników również miałyby sens. Jak w tym wszystkie przedziały czasowe w danym przedziale czasowym lub po prostu przedziały czasowe z rzeczywistymi wartościami. Wszystko możliwe, musiałem wybrać jedną interpretację.

Indeks

Miej przynajmniej ten wielokolumnowy indeks:

CRATE INDEX foo_idx ON tbl (sn, ts);

Lub na (sn, ts, vin1, vin2, vin3) aby umożliwić skanowanie tylko indeksu - jeśli spełnione są pewne warunki wstępne, a zwłaszcza jeśli wiersze tabeli są znacznie szersze niż w wersji demonstracyjnej.

Ściśle powiązane:

Na podstawie Twojej oryginalnej tabeli

Zgodnie z prośbą i wyjaśnieniem w komentarzu , a później ponownie zaktualizowane w pytaniu, aby uwzględnić kolumny mac i loc . Zakładam, że potrzebujesz oddzielnych średnich na (mac, loc) .

data i czas są nadal oddzielnymi kolumnami, kolumny vin* są typu float i wyklucz przedziały czasowe bez wierszy:

Zaktualizowane zapytanie przenosi również funkcję zwracającą zestaw generate_series() do OD lista, która jest czystsza przed Postgresem 10:

SELECT t.mac, sn.sn, t.loc, ts.ts::time AS time, ts.ts::date AS date
     , t.vin1_av, t.vin2_av, t.vin3_av
FROM  (SELECT text '4as11111111') sn(sn)  -- provide sn here once
CROSS  JOIN LATERAL (
   SELECT min(date+time) AS min_ts, max(date+time) AS max_ts
   FROM   tbl
   WHERE  sn = sn.sn
   AND    date+time >= '2018-01-01 0:0'   -- provide time frame here
   AND    date+time <  '2018-01-02 0:0'
   ) grid
CROSS  JOIN LATERAL generate_series(min_ts, max_ts, interval '5 min') ts(ts)
CROSS  JOIN LATERAL (
   SELECT mac, loc
        , round(avg(vin1)::numeric, 2) AS vin1_av  -- cast to numeric for round()
        , round(avg(vin2)::numeric, 2) AS vin2_av  -- but rounding is optional
        , round(avg(vin3)::numeric, 2) AS vin3_av
   FROM   tbl
   WHERE  sn = sn.sn
   AND    date+time >= ts.ts
   AND    date+time <  ts.ts + interval '5 min'
   GROUP  BY mac, loc
   HAVING count(*) > 0  -- exclude empty slots
   ) t;

Utwórz indeks wyrażeń wielokolumnowych do obsługi tego:

CRATE INDEX bar_idx ON tbl (sn, (date+time));

db<>fiddle tutaj

Ale wolałbym używać sygnatury czasowej przez cały czas.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dlaczego sekwencje identyfikatorów SQL nie są zsynchronizowane (w szczególności przy użyciu Postgresa)?

  2. Jak dołączyć do stołów na regex

  3. Hibernacja problemu z pobieraniem bajtów postgres

  4. PostgreSQL - nie można zidentyfikować operatora równości dla typu json

  5. kontekst wykonania wyzwalacza bazy danych w PostgreSQL