다음을 통해 공유


창 프레임 조항

적용 대상:체크 표시된 예 Databricks SQL 체크 표시된 예 Databricks Runtime

집계 또는 분석 창 함수가 작동하는 파티션 내 행의 슬라이딩 하위 집합을 지정합니다.

구문

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

매개 변수

  • frame_mode

    • ROWS

      지정된 경우 슬라이딩 윈도우 프레임은 현재 행 앞이나 뒤에 있는 행으로 표현됩니다.

    • 범위

      지정한 경우 창 함수는 단일 식 ORDER BY이 있는 절을 지정해야 합니다.

      그러면 슬라이딩 윈도우의 경계가 현재 행의 obExpr에서 오프셋으로 표현됩니다.

  • frame_start

    현재 행을 기준으로 슬라이딩 윈도우 프레임의 시작 위치입니다.

    • 무한 이전

      윈도우 프레임이 파티션의 시작 부분에서 시작되도록 지정합니다.

    • 앞의 offset_start

      모드가 ROWS인 경우 offset_start는 현재 행의 몇 개 행 앞에서 프레임이 시작되는지 정의하는 양의 정수 리터럴 숫자입니다.

      모드가 RANGE인 경우 offset_startobExpr에서 뺄 수 있는 형식의 양수 리터럴 값입니다. 프레임은 현재 행에서 obExprobExpr - offset_start보다 크거나 같은 파티션의 첫 번째 행에서 시작됩니다.

    • 현재 행

      프레임이 현재 행에서 시작되도록 지정합니다.

    • 오프셋_시작 후속

      모드가 ROWS인 경우 offset_start는 현재 행의 몇 개 행 뒤에서 프레임이 시작되는지 정의하는 양의 정수 리터럴 숫자입니다. 모드가 RANGE인 경우 offset_startobExpr에서 더할 수 있는 형식의 양수 리터럴 값입니다. 프레임은 현재 행에서 obExprobExpr + offset_start보다 크거나 같은 파티션의 첫 번째 행에서 시작됩니다.

  • frame_stop

    현재 행을 기준으로 슬라이딩 윈도우 프레임의 끝입니다.

    지정하지 않을 경우, 프레임은 현재 행에서 멈춥니다. 슬라이딩 윈도우의 끝은 윈도우 프레임의 시작 위치보다 커야 합니다.

    • 앞에 offset_stop

      frame_mode가 ROWS인 경우 offset_stop은 현재 행의 몇 개 행 앞에서 프레임이 중지되는지 정의하는 양의 정수 리터럴 숫자입니다. frame_mode가 RANGE인 경우 offset_stopoffset_start와 같은 형식의 양수 리터럴 값입니다. 프레임은 현재 행에서 obExprobExpr - offset_stop보다 작거나 같은 상태인 파티션의 마지막 행에서 끝납니다.

    • 현재 행

      프레임이 현재 행에서 중지되도록 지정합니다.

    • 다음 offset_stop

      frame_mode가 ROWS인 경우 offset_stop은 현재 행의 몇 개 행 뒤에서 프레임이 끝나는지 정의하는 양의 정수 리터럴 숫자입니다. frame_mode가 RANGE인 경우 offset_stopoffset_start와 같은 형식의 양수 리터럴 값입니다. 프레임은 현재 행에서 obExprobExpr + offset_stop보다 작거나 같은 파티션의 마지막 행에서 끝납니다.

    • 무한한 추적

      윈도우 프레임이 파티션의 끝에서 중지하도록 지정합니다.

예제

> 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