Собесов

SQL — отсортировать список в обратном порядке через ROW_NUMBER

SQLWindow-функцииЛёгкаяMiddle

Условие

Дана таблица task_2(name) с колонкой имён в неком исходном порядке (например: Кристина, Марина, Анна, Виктория, Светлана, Инна, Мария, Ольга, Анастасия, Ирина, Елена). Напишите SQL-запрос, который вернёт список в обратном порядке относительно исходного.

Хитрость: «исходный порядок» в реляционной таблице официально не существует — но задача проверяет, понимает ли кандидат идею с присвоением номера строки и сортировкой по нему в обратную сторону.

Решение

Подход

Эталон из ответов задания:

  1. Присваиваем строкам номер через ROW_NUMBER() OVER () (без ORDER BY — берётся «текущий» порядок выдачи).
  2. Сортируем по этому номеру в DESC.
SELECT name, ROW_NUMBER() OVER () AS rn
FROM task_2
ORDER BY rn DESC;

Так в результат вернётся последний элемент исходной выдачи первым, и т.д.

Что не так с этим подходом «по-чесному»

В стандарте SQL ROW_NUMBER() OVER () без ORDER BY имеет детерминированный порядок только в рамках одного выполнения и одной сортировки оптимизатора. На разных запусках порядок может меняться (особенно после VACUUM, изменения статистики, параллельного плана). Поэтому это решение работает на демо-данных, но в продакшне опасно.

Корректное решение: явный ключ сортировки

Если в таблице есть колонка, задающая порядок (например, id или created_at), сортировку нужно делать по ней:

SELECT name, ROW_NUMBER() OVER (ORDER BY id) AS rn_asc,
              ROW_NUMBER() OVER (ORDER BY id DESC) AS rn_desc
FROM task_2
ORDER BY id DESC;

Если такой колонки нет — добавляйте суррогат при загрузке. «Порядок строк» — антипаттерн в чистой реляционной модели.

Подводные камни

  1. Нет гарантии порядка без ORDER BY. Запрос SELECT * FROM task_2 может вернуть строки в любом порядке между запусками. Полагаться на «как лежат» нельзя.
  2. Window без ORDER BY в строгих диалектах. Некоторые СУБД (например, Oracle до 12c) ругаются на ROW_NUMBER() OVER () — требуют ORDER BY внутри OVER. В Postgres/MySQL/MS SQL разрешено.
  3. Разные ORDER BY для нумерации и финальной сортировки. Можно нумеровать по одному ключу, а финальный порядок задавать другим — это две разные операции.

Эталонный ответ

SELECT name, ROW_NUMBER() OVER () AS rn
FROM task_2
ORDER BY rn DESC;

На собесе после такого ответа стоит сразу проговорить риск: «Это работает на демо, но в продакшне нужен явный ключ сортировки — иначе порядок не гарантирован».

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти