Rekursiver CTE
Da jede Zeile von der vorherigen abhängt, ist sie mit einem mengenbasierten Ansatz schwer zu lösen. Rückgriff auf einen rekursiven CTE (was Standard-SQL ist):
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;
Beachten Sie die Aktualisierung meines ersten Entwurfs:
Aggregatfunktionen sind in einem rekursiven CTE nicht zulässig. Ich habe durch ORDER BY
ersetzt / LIMIT 1
, was schnell sein sollte, wenn es von einem Index unterstützt wird auf ts
.
Die Klammern um jedes Bein der UNION
Abfrage sind notwendig, um LIMIT
zuzulassen , was sonst nur einmal am Ende einer UNION
erlaubt wäre Abfrage.
PL/pgSQL-Funktion
Eine prozedurale Lösung (Beispiel mit einer plpgsql-Funktion), die durch die sortierte Tabelle iteriert, wäre wahrscheinlich viel schneller, da sie mit einem einzelnen Tabellenscan auskommt:
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;
Aufruf:
SELECT * FROM f_rowgrid('5 min')
SQL-Fiddle demonstriert beides.
Hier ist ein etwas komplexeres Beispiel für diese Art von plpgsql-Funktion:
Könnte leicht mit dynamischem SQL und EXECUTE
generisch gemacht werden um für beliebige Tabellen zu arbeiten.