ORDER BY

Только ORDER BY гарантирует порядок строк результата.

SELECT id, user_id, created_at
FROM orders
ORDER BY created_at DESC, id DESC;

id добавлен как уникальный tie-breaker. Без него строки с одинаковым created_at могут менять взаимный порядок, особенно между страницами.

NULL

Положение NULL зависит от СУБД и направления сортировки. Где поддерживается, намерение задают явно:

ORDER BY shipped_at DESC NULLS LAST

Для переносимости можно использовать CASE, но это может повлиять на индекс и план.

Индекс и сортировка

CREATE INDEX idx_orders_created_id
    ON orders (created_at DESC, id DESC);

Индекс может отдать строки в нужном порядке и убрать отдельную сортировку, если фильтр и направление совместимы. Но чтение большой доли таблицы или несовместимый префикс могут сделать другой план дешевле.

Выражения и псевдонимы

SELECT user_id, SUM(total) AS amount
FROM orders
GROUP BY user_id
ORDER BY amount DESC, user_id;

Псевдоним результата обычно разрешен в ORDER BY, потому что сортировка логически идет после SELECT.

Ловушки

  • Порядок строк в таблице, индексе или подзапросе не является контрактом внешнего запроса.
  • Сортировка строк зависит от collation.
  • Большая сортировка может выйти во временные файлы.
  • ORDER BY RANDOM() часто требует работу со всем набором.

Связано: Оператор LIMIT, Индексы SQL, SQL оценка производительности.

Вопросы

Почему нужен уникальный tie-breaker? Для детерминированного порядка равных ключей и стабильной пагинации.

Гарантирует ли primary key порядок без ORDER BY? Нет.

Когда индекс убирает сортировку? Когда его порядок соответствует фильтру и требуемому ORDER BY.

Где окажется NULL? Зависит от СУБД; важное поведение задают явно.