- Brug
COALESCE
som @Justin leverede. -
Med
first_value()
/last_value()
du bruger for at tilføje enORDER BY
klausul til vinduesdefinitionen eller rækkefølgen er udefineret . Du har lige været heldig i eksemplet, fordi rækkerne tilfældigvis er i orden lige efter oprettelse af dummy-tabellen.
Når du tilføjerORDER BY
, ender standardvinduesrammen ved den aktuelle række , og du skal bruge specialtilfælde aflast_value()
ring - eller vend sorteringsrækkefølgen i vinduesrammen som vist i mit første eksempel. -
Når du genbruger en vinduesdefinition flere gange, et eksplicit
WINDOW
klausul forenkler syntaksen meget:
SELECT ring, part, ARRAY[
coalesce(
lag(part) OVER w
,first_value(part) OVER (PARTITION BY ring ORDER BY part DESC))
,part
,coalesce(
lead(part) OVER w
,first_value(part) OVER w)
] AS neighbours
FROM rp
WINDOW w AS (PARTITION BY ring ORDER BY part);
Bedre endnu , genbrug den samme vinduesdefinition, så Postgres kan beregne alle værdier i en enkelt scanning. For at dette skal virke, skal vi definere en brugerdefineret vinduesramme :
SELECT ring, part, ARRAY[
coalesce(
lag(part) OVER w
,last_value(part) OVER w)
,part
,coalesce(
lead(part) OVER w
,first_value(part) OVER w)
] AS neighbours
FROM rp
WINDOW w AS (PARTITION BY ring
ORDER BY part
RANGE BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING)
ORDER BY 1,2;
Du kan endda tilpasse rammedefinitionen for hvert vinduesfunktionskald:
SELECT ring, part, ARRAY[
coalesce(
lag(part) OVER w
,last_value(part) OVER (w RANGE BETWEEN CURRENT ROW
AND UNBOUNDED FOLLOWING))
,part
,coalesce(
lead(part) OVER w
,first_value(part) OVER w)
] AS neighbours
FROM rp
WINDOW w AS (PARTITION BY ring ORDER BY part)
ORDER BY 1,2;
Måske hurtigere for ringe med mange dele. Du bliver nødt til at teste.
SQL Fiddle demonstrerer alle tre med en forbedret testcase. Overvej forespørgselsplaner.
Mere om vinduesrammedefinitioner:
- I manualen.
- PostgreSQL-vinduefunktion:partition ved sammenligning
- PostgreSQL-forespørgsel med maks. og min. dato plus tilknyttet id pr. række