- Använd
COALESCE
som @Justin gav. -
Med
first_value()
/last_value()
du behöver för att lägga till enORDER BY
klausul till fönsterdefinitionen eller så är ordningen odefinierad . Du hade precis tur i exemplet, eftersom raderna råkar vara i ordning direkt efter att du har skapat dummytabellen.
När du har lagt tillORDER BY
, slutar standardfönsterramen vid den aktuella raden , och du behöver specialfallalast_value()
ring - eller återställ sorteringsordningen i fönsterramen som visas i mitt första exempel. -
När du återanvänder en fönsterdefinition flera gånger, ett explicit
WINDOW
sats förenklar syntaxen mycket:
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);
Ännu bättre , återanvänd samma fönsterdefinition, så att Postgres kan beräkna alla värden i en enda skanning. För att detta ska fungera måste vi definiera en anpassad fönsterram :
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 till och med anpassa ramdefinitionen för varje fönsterfunktionsanrop:
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;
Kan vara snabbare för ringar med många delar. Du måste testa.
SQL Fiddle demonstrerar alla tre med ett förbättrat testfall. Överväg frågeplaner.
Mer om definitioner av fönsterkarmar:
- I manualen.
- PostgreSQL-fönsterfunktion:partition i jämförelse
- PostgreSQL-fråga med max- och mindatum plus tillhörande id per rad