CTE recursiva
Como cada linha depende da anterior, é difícil resolver com uma abordagem baseada em conjuntos. Recorrendo a um CTE recursivo (que é SQL padrão):
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;
Observe a atualização do meu primeiro rascunho:
Funções agregadas não são permitidas em uma CTE recursiva. Substituí por
ORDER BY
/ LIMIT 1
, que deve ser rápido quando suportado por um índice em ts
. Os parênteses em torno de cada perna do
UNION
query são necessários para permitir LIMIT
, que de outra forma só seria permitido uma vez no final de um UNION
consulta. Função PL/pgSQL
Uma solução procedural (exemplo com uma função plpgsql) iterando pela tabela classificada provavelmente seria muito mais rápida, pois pode se contentar com uma única varredura de tabela:
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;
Ligar:
SELECT * FROM f_rowgrid('5 min')
SQL Fiddle demonstrando ambos.
Aqui está um exemplo um pouco mais complexo para este tipo de função plpgsql:
Poderia ser facilmente genérico com SQL dinâmico e
EXECUTE
para trabalhar para tabelas arbitrárias.