CTE recursivo
Dado que cada fila depende de la anterior, es difícil de resolver con un enfoque basado en conjuntos. Recurrir a un CTE recursivo (que es SQL estándar):
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;
Tenga en cuenta la actualización de mi primer borrador:
Las funciones agregadas no están permitidas en un CTE recursivo. Lo sustituí con ORDER BY
/ LIMIT 1
, que debería ser rápido cuando lo admita un índice en ts
.
Los paréntesis alrededor de cada pata de UNION
consulta son necesarios para permitir LIMIT
, que de otro modo solo estaría permitido una vez al final de un UNION
consulta.
Función PL/pgSQL
Una solución de procedimiento (ejemplo con una función plpgsql) iterando a través de la tabla ordenada probablemente sería mucho más rápida, ya que puede arreglárselas con un solo escaneo de tabla:
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;
Llamar:
SELECT * FROM f_rowgrid('5 min')
SQL Fiddle demostrando ambos.
Aquí hay un ejemplo algo más complejo para este tipo de función plpgsql:
Podría convertirse fácilmente en genérico con SQL dinámico y EXECUTE
para trabajar con tablas arbitrarias.