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

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

📁 Блок: SQL / MySQL / Оконные функции ⏱️ Время изучения: ~90 мин 🎯 Сложность: Продвинутая

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

  • Путать RANK и DENSE_RANK.
  • Забывать ORDER BY внутри OVER.
  • Фильтровать по псевдониму оконной функции в WHERE.
  • Ожидать от NTILE строго равных групп при любом числе строк.
1

Ошибка: путаница между RANK и DENSE_RANK

Если задача требует ранг без пропусков, а используется RANK(), результат будет неправильным.

-- Неправильно: здесь нужен DENSE_RANK
SELECT
    product_name,
    RANK() OVER (ORDER BY standard_cost DESC) AS cost_rank
FROM products;

Как исправить: заменить на DENSE_RANK(), когда не должно быть пропусков.

-- Правильно
SELECT
    product_name,
    DENSE_RANK() OVER (ORDER BY standard_cost DESC) AS cost_rank
FROM products;
2

Ошибка: отсутствие ORDER BY в окне

Ранжирующие функции не знают, в каком порядке нумеровать строки, если не задан ORDER BY.

-- Неправильно: синтаксическая ошибка или непредсказуемый результат
SELECT
    product_name,
    ROW_NUMBER() OVER () AS row_num
FROM products;

Как исправить: добавить ORDER BY внутри OVER.

-- Правильно
SELECT
    product_name,
    ROW_NUMBER() OVER (ORDER BY product_name) AS row_num
FROM products;
3

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

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

-- Неправильно
SELECT
    product_name,
    DENSE_RANK() OVER (ORDER BY standard_cost DESC) AS cost_rank
FROM products
WHERE cost_rank <= 10;

Как исправить: обернуть запрос в подзапрос или CTE.

-- Правильно
SELECT product_name, cost_rank
FROM (
    SELECT
        product_name,
        DENSE_RANK() OVER (ORDER BY standard_cost DESC) AS cost_rank
    FROM products
) ranked
WHERE cost_rank <= 10;
4

Ошибка: неравные группы в NTILE

Если число строк не делится нацело на количество групп, NTILE добавляет «лишние» строки к первым группам. Это нормальное поведение, но о нём часто забывают.

-- При 5 строках и NTILE(4) группы будут: 2, 1, 1, 1 строка
SELECT
    product_name,
    list_price,
    NTILE(4) OVER (ORDER BY list_price) AS price_group
FROM products;

Как исправить: если нужны строго равные группы, используйте ROW_NUMBER() и арифметику или пересмотрите число групп.