sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur man använder en ringdatastruktur i fönsterfunktioner

  • Använd COALESCE som @Justin gav.
  • Med first_value() / last_value() du behöver för att lägga till en ORDER 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 till ORDER BY , slutar standardfönsterramen vid den aktuella raden , och du behöver specialfalla last_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


  1. Finns det något sätt att använda Linq till Oracle

  2. Oracle-proceduren returnerar inte resultat när den körs från skriptuppgiften på SSIS

  3. Hur mycket diskutrymme behövs för att lagra ett NULL-värde med postgresql DB?

  4. Android ListView:hur undviker man databasfråga i bindView()? Behöver hämta en till många relationsdata