ORDER BY и LIMIT в SQL — сортировка и ограничение результатов
Коротко
ORDER BY сортирует результат запроса по одному или нескольким столбцам. LIMIT ограничивает количество возвращаемых строк. Вместе они решают типичные задачи аналитика: найти топ-N, вытащить последние записи, сделать пагинацию.
ORDER BY — синтаксис
SELECT name, salary
FROM employees
ORDER BY salary DESC;По умолчанию сортировка по возрастанию (ASC). Чтобы отсортировать по убыванию — добавляем DESC.
Сортировка по нескольким столбцам
Можно указать несколько столбцов через запятую. SQL сначала сортирует по первому, а при одинаковых значениях — по второму:
SELECT department, name, salary
FROM employees
ORDER BY department ASC, salary DESC;Сотрудники сгруппируются по отделам в алфавитном порядке, внутри каждого отдела — по убыванию зарплаты.
Сортировка по номеру столбца
Вместо имени столбца можно указать его порядковый номер в SELECT:
SELECT name, salary
FROM employees
ORDER BY 2 DESC;Здесь 2 — это salary. Удобно для быстрых запросов, но в продакшн-коде лучше писать имена явно — так читаемее.
ORDER BY с выражениями
Сортировать можно не только по столбцам, но и по выражениям:
SELECT name, salary, bonus
FROM employees
ORDER BY salary + bonus DESC;NULL в сортировке
При сортировке NULL-значения по умолчанию попадают в конец (PostgreSQL при ASC) или в начало — зависит от СУБД. Чтобы управлять этим явно, используйте NULLS FIRST / NULLS LAST:
SELECT name, manager_id
FROM employees
ORDER BY manager_id ASC NULLS LAST;Это работает в PostgreSQL и Oracle. В MySQL такого синтаксиса нет — придётся использовать трюк:
-- MySQL: NULL в конец при ASC
ORDER BY manager_id IS NULL, manager_id ASC;LIMIT — ограничение результата
LIMIT задаёт максимальное количество строк в результате:
SELECT name, salary
FROM employees
ORDER BY salary DESC
LIMIT 10;Вернёт 10 самых высокооплачиваемых сотрудников.
Разница между СУБД
| Синтаксис | СУБД |
|---|---|
LIMIT 10 |
PostgreSQL, MySQL, SQLite, ClickHouse |
TOP 10 (после SELECT) |
SQL Server |
FETCH FIRST 10 ROWS ONLY |
Стандарт SQL, PostgreSQL, Oracle 12c+ |
-- SQL Server
SELECT TOP 10 name, salary
FROM employees
ORDER BY salary DESC;
-- Стандартный SQL (ANSI)
SELECT name, salary
FROM employees
ORDER BY salary DESC
FETCH FIRST 10 ROWS ONLY;На собеседовании обычно ожидают PostgreSQL-синтаксис с LIMIT, но знать альтернативы полезно.
OFFSET — пропуск строк
OFFSET пропускает первые N строк. Используется для пагинации:
SELECT name, created_at
FROM orders
ORDER BY created_at DESC
LIMIT 20 OFFSET 40;Этот запрос пропустит первые 40 строк и вернёт строки 41–60. Это третья «страница» по 20 записей.
Проблема производительности OFFSET
OFFSET работает наивно: СУБД читает и отбрасывает все пропущенные строки. При OFFSET 1000000 база прочитает миллион строк впустую. Для больших таблиц лучше использовать keyset pagination (курсорная пагинация):
-- Вместо OFFSET
SELECT id, name, created_at
FROM orders
WHERE created_at < '2025-12-01'
ORDER BY created_at DESC
LIMIT 20;Фильтруем по последнему значению с предыдущей страницы — это работает через индекс и не замедляется на больших смещениях.
Практические примеры
Топ-5 клиентов по выручке
SELECT customer_id, SUM(amount) AS total
FROM orders
GROUP BY customer_id
ORDER BY total DESC
LIMIT 5;Последние 10 заказов
SELECT order_id, customer_id, created_at
FROM orders
ORDER BY created_at DESC
LIMIT 10;Второй по величине элемент
Классическая задача с собеседования — найти вторую по величине зарплату:
SELECT DISTINCT salary
FROM employees
ORDER BY salary DESC
LIMIT 1 OFFSET 1;Типичные ошибки
ORDER BY в подзапросе. В PostgreSQL сортировка в подзапросе игнорируется, если внешний запрос не гарантирует порядок. Результат подзапроса — это множество, а у множеств нет порядка:
-- Порядок не гарантирован
SELECT * FROM (
SELECT name, salary FROM employees ORDER BY salary DESC
) sub
LIMIT 5;Правильно — ставить ORDER BY во внешнем запросе.
LIMIT без ORDER BY. Без сортировки LIMIT вернёт произвольные строки. Результат будет непредсказуемым и может меняться между запусками.
Вопросы с собеседований
«Что вернёт LIMIT без ORDER BY?» — Произвольные строки. Порядок не определён стандартом SQL, и СУБД может вернуть строки в любом порядке.
«Как найти N-ю по величине зарплату?» — ORDER BY salary DESC, затем LIMIT 1 OFFSET N-1. Либо через оконную функцию DENSE_RANK().
«Чем LIMIT отличается от FETCH FIRST?» — LIMIT — расширение PostgreSQL/MySQL. FETCH FIRST — стандарт ANSI SQL. Логика одинаковая, синтаксис разный.
«Как обрабатываются NULL при ORDER BY?» — Зависит от СУБД. В PostgreSQL при ASC NULL идут в конец, при DESC — в начало. Управлять можно через NULLS FIRST / NULLS LAST.
«Почему OFFSET медленный на больших значениях?» — Потому что СУБД физически читает и отбрасывает все пропущенные строки. Для эффективной пагинации используют keyset pagination — фильтрацию по последнему значению предыдущей страницы.
Потренируйтесь писать запросы с ORDER BY и LIMIT — откройте тренажёр с 1500+ вопросами по SQL. Больше теории — в гайде SQL для начинающих, больше задач — на странице с примерами вопросов.
FAQ
Можно ли сортировать по столбцу, которого нет в SELECT?
Да. ORDER BY может ссылаться на любой столбец таблицы, даже если он не указан в SELECT. Исключение — запросы с DISTINCT: сортировать можно только по выбранным столбцам.
Работает ли ORDER BY с алиасами?
Да, в большинстве СУБД. ORDER BY выполняется после SELECT, поэтому видит алиасы. Но в WHERE алиасы использовать нельзя — он выполняется раньше.
Что будет, если LIMIT больше, чем строк в таблице?
SQL вернёт все имеющиеся строки без ошибки. LIMIT — это верхняя граница, а не точное количество.
Можно ли использовать LIMIT без OFFSET?
Да, и в большинстве случаев так и делают. OFFSET нужен только для пагинации. Для задач вроде «топ-10» достаточно одного LIMIT.