- Gebruik
COALESCE
zoals @Justin heeft opgegeven. -
Met
first_value()
/last_value()
je nodig om een ORDER BY
. toe te voegen clausule aan de vensterdefinitie of de bestelling is undefined . In het voorbeeld heb je gewoon geluk gehad, omdat de rijen toevallig in de juiste volgorde staan direct na het maken van de dummy-tabel.
Zodra jeORDER BY
hebt toegevoegd , het standaard raamkozijn eindigt op de huidige rij , en je moet delast_value()
. speciaal maken bel - of keer de sorteervolgorde in het raamkozijn terug, zoals aangetoond in mijn eerste voorbeeld. -
Wanneer een vensterdefinitie meerdere keren wordt hergebruikt, wordt een expliciete
WINDOW
clausule vereenvoudigt de syntaxis veel:
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);
Beter nog , hergebruik dezelfde vensterdefinitie, zodat Postgres alle waarden in één scan kan berekenen. Om dit te laten werken, moeten we een aangepast raamkozijn definiëren :
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;
U kunt zelfs de framedefinitie voor elke vensterfunctie-aanroep aanpassen:
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;
Misschien sneller voor ringen met veel onderdelen. Je zult moeten testen.
SQL Fiddle alle drie demonstreren met een verbeterde testcase. Overweeg queryplannen.
Meer over definities van raamkozijnen:
- In de handleiding.
- PostgreSQL-vensterfunctie:partitie door vergelijking
- PostgreSQL-query met max en min datum plus bijbehorende id per rij