ORDER BY управляет порядком строк только в финальном результате запроса. В подзапросах и CTE он не гарантирует порядок строк, если не используется вместе с ограничением количества возвращаемых данных.Причина в том, что оптимизатор может свободно менять план выполнения, пока итоговый результат формально остаётся корректным.
Таблица событий:
events(id, user_id, created_at)
Попытка взять последние события через подзапрос:
SELECT *
FROM (
SELECT *
FROM events
ORDER BY created_at DESC
) t;
Несмотря на явный
ORDER BY внутри подзапроса, внешний запрос не содержит сортировки.Это означает, что порядок строк на выходе не определён, и СУБД имеет право проигнорировать внутреннюю сортировку как не влияющую на результат.
Корректный вариант — сортировать во внешнем запросе:
SELECT *
FROM events
ORDER BY created_at DESC;
Именно этот
ORDER BY гарантирует порядок строк, который получит клиент или приложение.Когда
ORDER BY в подзапросе имеет смысл — он становится значимым только вместе с ограничением:SELECT *
FROM (
SELECT *
FROM events
ORDER BY created_at DESC
LIMIT 10
) t
ORDER BY created_at DESC;
В этом случае сортировка в подзапросе используется для выбора нужных строк, а не для их отображения.
Внутренний
ORDER BY определяет, какие именно 10 строк попадут в подзапрос, а внешний ORDER BY задаёт порядок финального результата.Аналогичный принцип работает с оконными функциями:
SELECT id, user_id, created_at
FROM (
SELECT
id,
user_id,
created_at,
ROW_NUMBER() OVER (
PARTITION BY user_id
ORDER BY created_at DESC
) AS rn
FROM events
) s
WHERE rn = 1;
Здесь
ORDER BY влияет на вычисление ROW_NUMBER, то есть на логику нумерации строк внутри окна, но не определяет порядок вывода строк в результирующем наборе.🔥
ORDER BY — это про порядок выдачи результата, а не про порядок хранения данных. Без внешнего ORDER BY СУБД не обязана возвращать строки в каком-либо определённом порядке.➡️ SQL Ready | #практика