Compartir vía


Cláusula de marco de ventana

Se aplica a:casilla marcada como Sí Databricks SQL casilla marcada como Sí Databricks Runtime

Especifica un subconjunto deslizante de filas dentro de la partición en la que opera la función de ventana de agregado o analítica.

Sintaxis

{ 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 }

Parámetros

  • frame_mode

    • ROWS

      Si se especifica, el marco de la ventana deslizante se expresa en términos de filas anteriores o siguientes a la fila actual.

    • RANGE

      Si se especifica, la función de ventana debe especificar una cláusula ORDER BY con una expresión única obExpr.

      A continuación, los límites de la ventana deslizante se expresan como un desplazamiento desde obExpr para la fila actual.

  • frame_start

    Posición inicial del marco de la ventana deslizante con respecto a la fila actual.

    • SIN LÍMITES PRECEDIDOS

      Especifica que el marco de la ventana comienza al principio de la partición.

    • es-ES: offset_start PRECEDENTE

      Si el modo es ROWS, offset_start es el número literal integral positivo que define cuántas filas antes de la fila actual se inicia el marco.

      Si el modo es RANGE, offset_start es un valor literal positivo de un tipo que se puede restar de obExpr. El marco comienza en la primera fila de la partición para la que obExpr es mayor o igual a obExpr - offset_start en la fila actual.

    • FILA ACTUAL

      Especifica que el marco comienza en la fila actual.

    • offset_start SIGUIENTE

      Si el modo es ROWS, offset_start es el número literal integral positivo que define cuántas filas después de la fila actual se inicia el marco. Si el modo es RANGE, offset_start es un valor literal positivo de un tipo que se puede sumar a obExpr. El marco comienza en la primera fila de la partición para la que obExpr es mayor o igual a obExpr + offset_start en la fila actual.

  • frame_stop

    Posición final del marco de la ventana deslizante con respecto a la fila actual.

    Si no se especifica, el marco se detiene en CURRENT ROW. La posición final de la ventana deslizante debe ser mayor que la posición inicial del marco de la ventana.

    • offset_stop ANTERIOR

      Si frame_mode es ROWS, offset_stop es el número literal integral positivo que define cuántas filas antes de la fila actual se detiene el marco. Si frame_mode es RANGE, offset_stop es un valor literal positivo del mismo tipo que offset_start. El marco finaliza en la última fila fuera de la partición para la que obExpr es menor o igual a obExpr - offset_stop en la fila actual.

    • FILA ACTUAL

      Especifica que el marco se detiene en la fila actual.

    • offset_stop SIGUIENTE

      Si frame_mode es ROWS, offset_stop es el número literal integral positivo que define cuántas filas después de la fila actual finaliza el marco. Si frame_mode es RANGE, offset_stop es un valor literal positivo del mismo tipo que offset_start. El marco finaliza en la última fila de la partición para la que obExpr es menor o igual a obExpr + offset_stop en la fila actual.

    • SEGUIMIENTO SIN LÍMITES

      Especifica que el marco de la ventana termina al final de la partición.

Ejemplos

> 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