← К оглавлению занятия

🐛 Типичные ошибки

⚡ Кратко: ошибки

  • Путать сортировку окна с сортировкой результата.
  • Думать, что PARTITION BY обязателен.
  • Использовать GROUP BY там, где нужна оконная функция.
  • Забывать, что оконные функции вычисляются после WHERE, но перед ORDER BY результата.
1

Ошибка: смешивание ORDER BY в окне и ORDER BY результата

Новички часто думают, что ORDER BY внутри OVER влияет на порядок строк в выводе.

-- Неправильное ожидание: результат отсортирован по salary
SELECT
    employee_id,
    department_id,
    salary,
    AVG(salary) OVER (PARTITION BY department_id ORDER BY salary)
FROM employees;

Как исправить: если нужна сортировка результата, добавьте ORDER BY в конец запроса.

-- Правильно
SELECT
    employee_id,
    department_id,
    salary,
    AVG(salary) OVER (PARTITION BY department_id)
FROM employees
ORDER BY department_id, salary;
2

Ошибка: лишнее GROUP BY рядом с оконной функцией

Использование GROUP BY вместе с оконной функцией без необходимости приводит к ошибкам или потере строк.

-- Неправильно: GROUP BY сворачивает строки, оконная функция уже не нужна
SELECT
    employee_id,
    department_id,
    COUNT(*) OVER (PARTITION BY department_id)
FROM employees
GROUP BY department_id;

Как исправить: уберите GROUP BY, если нужно сохранить все строки.

-- Правильно
SELECT
    employee_id,
    department_id,
    COUNT(*) OVER (PARTITION BY department_id) AS dept_count
FROM employees;
3

Ошибка: ожидание, что PARTITION BY обязателен

Некоторые думают, что без PARTITION BY оконная функция не работает. На самом деле OVER () задаёт окно из всех строк.

-- Правильно: окно охватывает все строки
SELECT
    employee_id,
    salary,
    SUM(salary) OVER () AS total_salary
FROM employees;
4

Ошибка: использование псевдонима оконной функции в WHERE

Оконные функции вычисляются после фильтрации WHERE, поэтому их псевдоним нельзя использовать в WHERE.

-- Неправильно
SELECT
    employee_id,
    department_id,
    COUNT(*) OVER (PARTITION BY department_id) AS dept_count
FROM employees
WHERE dept_count > 5;

Как исправить: используйте подзапрос или QUALIFY (в некоторых СУБД).

-- Правильно: подзапрос
SELECT *
FROM (
    SELECT
        employee_id,
        department_id,
        COUNT(*) OVER (PARTITION BY department_id) AS dept_count
    FROM employees
) sub
WHERE dept_count > 5;