sql >> Database teknologi >  >> RDS >> PostgreSQL

MySQL/Postgres forespørgsel efter 5 minutters intervaldata

Rekursiv CTE

Da hver række afhænger af den før, er det svært at løse med en sæt-baseret tilgang. At ty til en rekursiv CTE (som er standard SQL):

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;

Bemærk opdateringen fra mit første udkast:
Aggregerede funktioner er ikke tilladt i en rekursiv CTE. Jeg erstattede med ORDER BY / LIMIT 1 , hvilket burde være hurtigt, når det understøttes af et indeksts .

Parenteserne omkring hvert ben af ​​UNION forespørgsler er nødvendige for at tillade LIMIT , som ellers kun ville være tilladt én gang i slutningen af ​​en UNION forespørgsel.

PL/pgSQL-funktion

En proceduremæssig løsning (eksempel med en plpgsql-funktion), der gentager den sorterede tabel, ville sandsynligvis være meget hurtigere, da den kan nøjes med en enkelt tabelscanning:

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;
 

Ring til:

SELECT * FROM  f_rowgrid('5 min')
 

SQL Fiddle demonstrerer begge dele.

Her er et noget mere komplekst eksempel på denne type plpgsql-funktion:

Kan nemt gøres generisk med dynamisk SQL og EXECUTE at arbejde for vilkårlige tabeller.




  1. Hvordan beregner jeg et glidende gennemsnit ved hjælp af MySQL?

  2. Performance Tuning:Opret indeks for boolesk kolonne

  3. MySQL GroupBy og viser det vandret

  4. MySQL Vælg en anden række, hvis der ikke findes en