sql >> Base de Datos >  >> RDS >> PostgreSQL

MySQL/Postgres consulta datos de intervalo de 5 minutos

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.