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

Første og sidste værdi af vinduesfunktion i én række i PostgreSQL

Spørgsmålet er gammelt, men denne løsning er enklere og hurtigere end det, der hidtil er blevet postet:

SELECT b.machine_id
     , batch
     , timestamp_sta
     , timestamp_stp
     , min(timestamp_sta) OVER w AS batch_start
     , max(timestamp_stp) OVER w AS batch_end
FROM   db_data.sta_stp a
JOIN   db_data.ll_lu   b ON a.ll_lu_id = b.id
WINDOW w AS (PARTITION BY batch, b.machine_id) -- No ORDER BY !
ORDER  BY timestamp_sta, batch, machine_id; -- why this ORDER BY?

Hvis du tilføjer ORDER BY til vinduesrammedefinitionen, hver næste række med en større ORDER BY udtryk har en senere rammestart. Hverken min() heller ikke first_value() kan returnere det "første" tidsstempel for hele partitionen derefter. Uden ORDER BY alle rækker i den samme partition er peers og du får det ønskede resultat.

Din tilføjede ORDER BY virker (ikke den i vinduesrammens definition, den ydre), men det ser ikke ud til at give mening og gør forespørgslen dyrere. Du skal nok bruge en ORDER BY klausul, der stemmer overens med din vinduesrammedefinition for at undgå yderligere sorteringsomkostninger:

... 
ORDER BY batch, b.machine_id, timestamp_sta, timestamp_stp;

Jeg kan ikke se behovet for DISTINCT i denne forespørgsel. Du kan bare tilføje det, hvis du rent faktisk har brug for det. Eller DISTINCT ON () . Men så ORDER BY klausul bliver endnu mere relevant. Se:

Hvis du har brug for nogle andre kolonne(r) fra samme række (mens du stadig sorterer efter tidsstempler), din idé med FIRST_VALUE() og LAST_VALUE() kan være vejen at gå. Du skal sandsynligvis tilføje dette til vinduesrammedefinitionen :

ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING

Se:



  1. Forespørg på et mange-til-mange forhold ved hjælp af Doctrine med Symfony2

  2. PostgreSQL - afrunding af flydende kommatal

  3. Indeks spænder over flere tabeller i PostgreSQL

  4. mysql feltnavn fra variabel