Dela via


Fönsterramsklausul

Gäller för:markerad ja Databricks SQL markerad ja Databricks Runtime

Anger en glidande delmängd av rader i partitionen där funktionen för aggregerade eller analytiska fönster fungerar.

Syntax

{ frame_mode frame_start |
  frame_mode BETWEEN frame_start AND frame_end } }

frame_mode
{ RANGE | ROWS }

frame_start
{ UNBOUNDED PRECEDING |
  offset_start PRECEDING |
  CURRENT ROW |
  offset_start FOLLOWING }

frame_end
{ offset_stop PRECEDING |
  CURRENT ROW |
  offset_stop FOLLOWING |
  UNBOUNDED FOLLOWING }

Parametrar

  • frame_mode

    • RADER

      Om det anges uttrycks skjutfönsterramen i termer av rader som föregår eller följer den aktuella raden.

    • SORTIMENT

      Om det anges måste fönsterfunktionen ange en ORDER BY-sats med ett enda uttryck obExpr.

      Gränserna för skjutfönstret uttrycks sedan som en förskjutning från obExpr för den aktuella raden.

  • frame_start

    Startpositionen för skjutfönsterramen i förhållande till den aktuella raden.

    • OGRÄNSAD FÖREGÅENDE

      Anger att fönsterramen startar i början av partitionen.

    • offset_start FÖREGÅENDE

      Om läget är ROWS, så är offset_start det positiva heltal som definierar hur många rader före den aktuella raden som ramen startar.

      Om läget är RANGE, offset_start är ett positivt literalvärde av en typ som kan subtraheras från obExpr. Ramen börjar vid den första raden i partitionen där obExpr är större än eller lika med obExpr - offset_start på den aktuella raden.

    • AKTUELL RAD

      Anger att ramen börjar på den aktuella raden.

    • offset_start FÖLJANDE

      Om läget är ROWS, offset_start är det positiva integralliterala talet som definierar hur många rader som går förbi till den aktuella raden som ramen startar. Om läget är RANGE, offset_start är ett positivt literalvärde av en typ som kan läggas till i obExpr. Ramen börjar vid den första raden i partitionen där obExpr är större än eller lika med obExpr + offset_start på den aktuella raden.

  • frame_stop

    Slutet på skjutfönstrets ram i förhållande till den aktuella raden.

    Om inget annat anges stannar ramen på AKTUELL RAD. Slutet av skjutfönstret måste vara större än början av fönsterramen.

    • OFFSET_STOP FÖREGÅENDE

      Om frame_mode är ROWS, så är offset_stop det positiva heltalet som anger hur många rader före den aktuella raden som ramen slutar. Om frame_mode är RANGE, offset_stop är ett positivt literalvärde av samma typ som offset_start. Ramen slutar vid den sista raden av partitionen där obExpr är mindre än eller lika med obExpr - offset_stop på den aktuella raden.

    • AKTUELL RAD

      Specificerar att ramens stopp sker på den aktuella raden.

    • offset_stop FÖLJANDE

      Om frame_mode är ROWS, är offset_stop det positiva heltal som definierar hur många rader bortom den aktuella raden som ramen slutar. Om frame_mode är RANGE, offset_stop är ett positivt literalvärde av samma typ som offset_start. Ramen slutar på den sista raden i partitionen för vilket obExpr är mindre än eller lika med obExpr + offset_stop vid den aktuella raden.

    • OBEGRÄNSAD FÖLJD

      Anger att fönsterramen slutar vid slutet av väggsektionen.

Exempel

> CREATE TABLE employees
   (name STRING, dept STRING, salary INT, age INT);
> INSERT INTO employees
   VALUES ('Lisa', 'Sales', 10000, 35),
          ('Evan', 'Sales', 32000, 38),
          ('Fred', 'Engineering', 21000, 28),
          ('Alex', 'Sales', 30000, 33),
          ('Tom', 'Engineering', 23000, 33),
          ('Jane', 'Marketing', 29000, 28),
          ('Jeff', 'Marketing', 35000, 38),
          ('Paul', 'Engineering', 29000, 23),
          ('Chloe', 'Engineering', 23000, 25);

-- ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW: cumulative sum of salary within each department.
> SELECT name,
         dept,
         salary,
         SUM(salary) OVER (PARTITION BY dept ORDER BY salary
                           ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_total
    FROM employees;
  Fred Engineering  21000  21000
 Chloe Engineering  23000  44000
   Tom Engineering  23000  67000
  Paul Engineering  29000  96000
  Jane   Marketing  29000  29000
  Jeff   Marketing  35000  64000
  Lisa       Sales  10000  10000
  Alex       Sales  30000  40000
  Evan       Sales  32000  72000

-- ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING: moving average over three adjacent rows.
> SELECT name,
         dept,
         salary,
         ROUND(AVG(salary) OVER (PARTITION BY dept ORDER BY salary
                                 ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)) AS moving_avg
    FROM employees;
  Fred Engineering  21000  22000
 Chloe Engineering  23000  22333
   Tom Engineering  23000  25000
  Paul Engineering  29000  26000
  Jane   Marketing  29000  32000
  Jeff   Marketing  35000  32000
  Lisa       Sales  10000  20000
  Alex       Sales  30000  24000
  Evan       Sales  32000  31000

-- ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING: sum from the current row to the end of the partition.
> SELECT name,
         dept,
         salary,
         SUM(salary) OVER (PARTITION BY dept ORDER BY salary
                           ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) AS remaining_total
    FROM employees;
  Fred Engineering  21000  96000
 Chloe Engineering  23000  75000
   Tom Engineering  23000  52000
  Paul Engineering  29000  29000
  Jane   Marketing  29000  64000
  Jeff   Marketing  35000  35000
  Lisa       Sales  10000  72000
  Alex       Sales  30000  62000
  Evan       Sales  32000  32000

-- RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW: cumulative sum using value-based range.
-- Unlike ROWS mode, RANGE groups rows with equal `ORDER BY` values together.
> SELECT name,
         dept,
         salary,
         SUM(salary) OVER (PARTITION BY dept ORDER BY salary
                           RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS range_total
    FROM employees;
  Fred Engineering  21000  21000
 Chloe Engineering  23000  67000
   Tom Engineering  23000  67000
  Paul Engineering  29000  96000
  Jane   Marketing  29000  29000
  Jeff   Marketing  35000  64000
  Lisa       Sales  10000  10000
  Alex       Sales  30000  40000
  Evan       Sales  32000  72000

-- RANGE BETWEEN 5000 PRECEDING AND 5000 FOLLOWING: sum of salaries within +/- 5000 of the current row's salary.
> SELECT name,
         dept,
         salary,
         SUM(salary) OVER (PARTITION BY dept ORDER BY salary
                           RANGE BETWEEN 5000 PRECEDING AND 5000 FOLLOWING) AS nearby_total
    FROM employees;
  Fred Engineering  21000  67000
 Chloe Engineering  23000  67000
   Tom Engineering  23000  67000
  Paul Engineering  29000  75000
  Jane   Marketing  29000  64000
  Jeff   Marketing  35000  35000
  Lisa       Sales  10000  10000
  Alex       Sales  30000  92000
  Evan       Sales  32000  62000

-- Comparing ROWS vs RANGE: the difference is visible when there are duplicate `ORDER BY` values.
-- With ROWS, `Chloe` and `Tom` have different running totals because each row is counted individually.
-- With RANGE, `Chloe` and `Tom` have the same total because they share the same salary value.
> SELECT name,
         salary,
         SUM(salary) OVER (ORDER BY salary
                           ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)  AS rows_total,
         SUM(salary) OVER (ORDER BY salary
                           RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS range_total
    FROM employees
    WHERE dept = 'Engineering';
  Fred  21000  21000  21000
 Chloe  23000  44000  67000
   Tom  23000  67000  67000
  Paul  29000  96000  96000