sql >> Database >  >> RDS >> PostgreSQL

Een ringgegevensstructuur gebruiken in vensterfuncties

  • 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 je ORDER BY hebt toegevoegd , het standaard raamkozijn eindigt op de huidige rij , en je moet de last_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


  1. Kun je een webservice aanroepen vanuit TSQL-code?

  2. Handtekening opslaan in MySQL

  3. MySQL Workbench:Fout in query (1064):Syntaxisfout bij 'VISIBLE' op regel 1

  4. Oracle RAC N+1 redundantie