Условие
Дана таблица task_2(name) с колонкой имён в неком исходном порядке (например: Кристина, Марина, Анна, Виктория, Светлана, Инна, Мария, Ольга, Анастасия, Ирина, Елена). Напишите SQL-запрос, который вернёт список в обратном порядке относительно исходного.
Хитрость: «исходный порядок» в реляционной таблице официально не существует — но задача проверяет, понимает ли кандидат идею с присвоением номера строки и сортировкой по нему в обратную сторону.
Решение
Подход
Эталон из ответов задания:
- Присваиваем строкам номер через
ROW_NUMBER() OVER ()(безORDER BY— берётся «текущий» порядок выдачи). - Сортируем по этому номеру в
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;Если такой колонки нет — добавляйте суррогат при загрузке. «Порядок строк» — антипаттерн в чистой реляционной модели.
Подводные камни
- Нет гарантии порядка без
ORDER BY. ЗапросSELECT * FROM task_2может вернуть строки в любом порядке между запусками. Полагаться на «как лежат» нельзя. - Window без
ORDER BYв строгих диалектах. Некоторые СУБД (например, Oracle до 12c) ругаются наROW_NUMBER() OVER ()— требуютORDER BYвнутриOVER. В Postgres/MySQL/MS SQL разрешено. - Разные
ORDER BYдля нумерации и финальной сортировки. Можно нумеровать по одному ключу, а финальный порядок задавать другим — это две разные операции.
Эталонный ответ
SELECT name, ROW_NUMBER() OVER () AS rn
FROM task_2
ORDER BY rn DESC;На собесе после такого ответа стоит сразу проговорить риск: «Это работает на демо, но в продакшне нужен явный ключ сортировки — иначе порядок не гарантирован».