PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

MySQL/Postgres interroge les données à intervalle de 5 minutes

CTE récursif

Étant donné que chaque ligne dépend de la précédente, il est difficile de résoudre avec une approche basée sur les ensembles. Recourir à un CTE récursif (qui est du 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;

Notez la mise à jour de mon premier brouillon :
Les fonctions d'agrégation ne sont pas autorisées dans un CTE récursif. J'ai remplacé par ORDER BY / LIMIT 1 , qui devrait être rapide lorsqu'il est pris en charge par un index sur ts .

Les parenthèses autour de chaque jambe de l'UNION requête sont nécessaires pour autoriser LIMIT , qui ne serait autrement autorisé qu'une seule fois à la fin d'un UNION requête.

Fonction PL/pgSQL

Une solution procédurale (exemple avec une fonction plpgsql) itérant dans la table triée serait probablement beaucoup plus rapide, car elle peut se contenter d'un seul parcours de table :

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;

Appel :

SELECT * FROM  f_rowgrid('5 min')

SQL Fiddle démontrant les deux.

Voici un exemple un peu plus complexe pour ce type de fonction plpgsql :

Pourrait facilement être rendu générique avec SQL dynamique et EXECUTE pour travailler avec des tables arbitraires.