PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

MySQL/Postgres interroga i dati a intervalli di 5 minuti

CTE ricorsivo

Poiché ogni riga dipende da quella precedente, è difficile da risolvere con un approccio basato sugli insiemi. Ricorrere a un CTE ricorsivo (che è SQL standard):

WITH RECURSIVE cte AS (
   (SELECT ts FROM tbl
    ORDER  BY ts
    LIMIT  1)

   UNION ALL
   (SELECT t.ts
    FROM   cte c
    JOIN   tbl t ON t.ts >= c.ts + interval '5 min'
    ORDER  BY t.ts
    LIMIT  1)
   )
SELECT * FROM cte ORDER BY ts;

Nota l'aggiornamento dalla mia prima bozza:
Le funzioni aggregate non sono consentite in un CTE ricorsivo. Ho sostituito con ORDER BY / LIMIT 1 , che dovrebbe essere veloce se supportato da un indice su ts .

Le parentesi attorno a ciascuna gamba di UNION query sono necessarie per consentire LIMIT , che altrimenti sarebbe consentito solo una volta alla fine di un UNION interrogazione.

Funzione PL/pgSQL

Una soluzione procedurale (esempio con una funzione plpgsql) che itera attraverso la tabella ordinata sarebbe probabilmente molto più veloce, poiché può accontentarsi di una scansione di una singola tabella:

CREATE OR REPLACE FUNCTION f_rowgrid(i interval)
  RETURNS SETOF timestamp AS
$func$
DECLARE
   _this  timestamp;
   _last  timestamp := '-infinity';     -- init so that 1 row passes
BEGIN

FOR _this IN
    SELECT ts FROM tbl ORDER BY 1
LOOP
    IF _this >= _last + i THEN
       RETURN NEXT _this;
       _last := _this;
    END IF;
END LOOP;

END
$func$ LANGUAGE plpgsql;

Chiama:

SELECT * FROM  f_rowgrid('5 min')

SQL Fiddle dimostrando entrambi.

Ecco un esempio un po' più complesso per questo tipo di funzione plpgsql:

Potrebbe essere facilmente reso generico con SQL dinamico e EXECUTE per lavorare con tabelle arbitrarie.