ORDER BY — это команда для сортировки результата запроса. Без неё база отдаёт строки в произвольном порядке (как ей удобнее), и для пользователя это выглядит как хаос. С ORDER BY ты явно говоришь: «отсортируй мне по этой колонке от меньшего к большему» (или наоборот).
Аналогия: представь стопку книг на столе, кинутых как попало. ORDER BY title — это «расставь по алфавиту названий». ORDER BY year DESC — «сначала самые новые, потом старые».
Зачем нужен ORDER BY
Безsortировки SQL не даёт никаких гарантий о порядке. Один и тот же запрос два раза подряд может вернуть строки в разном порядке. Поэтому если в результате важен порядок (топ-10 продаж, новости по дате, лидерборд) — ORDER BY обязателен.
Типичные сценарии:
- Списки в UI: показать товары от дешёвых к дорогим
- Рейтинги: топ-10 пользователей по очкам
- Хронология: посты от самых свежих к старым
- Алфавитные справочники: список городов от А до Я
Базовый синтаксис
SELECT *
FROM таблица
ORDER BY колонка [ASC | DESC];
ASC — ascending (по возрастанию). Это значение по умолчанию — можно опускать.
DESC — descending (по убыванию).
Пример: библиотека книг.
SELECT title, year
FROM books
ORDER BY year DESC;
Получим список книг от самой новой к самой старой.
Пример: библиотека
Таблица books:
| id |
title |
author |
year |
rating |
| 1 |
Война и мир |
Лев Толстой |
1869 |
4.8 |
| 2 |
Мастер и Маргарита |
Михаил Булгаков |
1967 |
4.9 |
| 3 |
Тихий Дон |
Михаил Шолохов |
1940 |
4.7 |
| 4 |
Преступление и наказание |
Фёдор Достоевский |
1866 |
4.8 |
Запрос — отсортировать по году издания (по возрастанию):
SELECT title, year FROM books ORDER BY year;
Результат:
| title |
year |
| Преступление и наказание |
1866 |
| Война и мир |
1869 |
| Тихий Дон |
1940 |
| Мастер и Маргарита |
1967 |
Самая старая — сверху. Если поменять на DESC, порядок перевернётся, самая новая будет первой.
Сортировка по нескольким колонкам
Часто одной колонки мало. Например, по году издания совпадение — нужно дополнительно отсортировать по рейтингу. Просто перечисляй через запятую:
SELECT title, year, rating
FROM books
ORDER BY year DESC, rating DESC;
Как это работает:
- Сначала база сортирует по
year DESC (новые сверху).
- Внутри одного и того же года — дополнительно сортирует по
rating DESC.
- Если бы было третье поле — оно бы сработало внутри одинаковых year+rating.
Это называется «многоуровневая сортировка». Очень частая штука: «сначала по дате, внутри даты — по приоритету», «сначала по статусу, внутри статуса — по сумме».
Пример с многоуровневой сортировкой. Таблица employees:
| id |
name |
department |
salary |
| 1 |
Анна |
IT |
120000 |
| 2 |
Борис |
Sales |
80000 |
| 3 |
Вера |
IT |
150000 |
| 4 |
Григорий |
HR |
70000 |
| 5 |
Денис |
IT |
120000 |
| 6 |
Елена |
Sales |
95000 |
Запрос: сначала по отделу (по алфавиту), внутри отдела — по зарплате (от большей к меньшей).
SELECT name, department, salary
FROM employees
ORDER BY department ASC, salary DESC;
Результат:
| name |
department |
salary |
| Григорий |
HR |
70000 |
| Вера |
IT |
150000 |
| Анна |
IT |
120000 |
| Денис |
IT |
120000 |
| Елена |
Sales |
95000 |
| Борис |
Sales |
80000 |
Отделы идут по алфавиту: HR → IT → Sales. Внутри IT — Вера (150к), потом Анна и Денис (по 120к, в произвольном порядке между собой), потом и так далее.
Если хочется детерминированный порядок и у Анны с Денисом — добавь третий уровень, например по имени: ORDER BY department ASC, salary DESC, name ASC.
Сортировка по выражению
В ORDER BY можно класть не только имена колонок, но и выражения:
SELECT title, likes, views
FROM posts
ORDER BY likes / views DESC;
Это отсортирует посты по «engagement rate» — отношению лайков к просмотрам. В таблице такой колонки нет, но база посчитает на лету.
Другой типичный сценарий — функции:
SELECT name FROM users ORDER BY LOWER(name);
LOWER приводит имя к нижнему регистру для регистронезависимой сортировки.
Топ-N: ORDER BY + LIMIT
Классическая комбинация. Чтобы получить «топ-3 поста по лайкам», нужно сначала отсортировать, потом обрезать:
SELECT title, likes
FROM posts
ORDER BY likes DESC
LIMIT 3;
Сначала ORDER BY likes DESC ставит самые залайканные сверху, потом LIMIT 3 берёт первые три. Без ORDER BY LIMIT 3 вернёт три случайные строки — это типичный баг новичков.
NULL в сортировке
Если в колонке есть NULL-значения, базы по-разному решают, куда их положить:
- PostgreSQL: при
ASC — NULL в конце, при DESC — в начале.
- MySQL: при
ASC — NULL в начале, при DESC — в конце.
Если важно явно — в PostgreSQL есть NULLS FIRST / NULLS LAST:
SELECT title, published_at
FROM posts
ORDER BY published_at DESC NULLS LAST;
Получим: сначала свежие посты, в самом конце — те, у которых даты публикации ещё нет (черновики). В MySQL такого синтаксиса нет, нужно делать через выражение: ORDER BY published_at IS NULL, published_at DESC.
Большой пример: до и после
Таблица orders:
| id |
customer |
amount |
status |
created_at |
| 1 |
Анна |
500 |
paid |
2024-03-10 |
| 2 |
Борис |
1500 |
paid |
2024-03-15 |
| 3 |
Вера |
200 |
cancelled |
2024-03-12 |
| 4 |
Григорий |
3000 |
paid |
2024-03-08 |
| 5 |
Денис |
800 |
pending |
2024-03-15 |
Запрос: «сначала оплаченные, потом ожидающие, потом отменённые. Внутри каждой группы — самые новые сверху, при равенстве дат — большие суммы первые».
SELECT id, customer, status, amount, created_at
FROM orders
ORDER BY
CASE status
WHEN 'paid' THEN 1
WHEN 'pending' THEN 2
WHEN 'cancelled' THEN 3
END,
created_at DESC,
amount DESC;
Результат:
| id |
customer |
status |
amount |
created_at |
| 2 |
Борис |
paid |
1500 |
2024-03-15 |
| 1 |
Анна |
paid |
500 |
2024-03-10 |
| 4 |
Григорий |
paid |
3000 |
2024-03-08 |
| 5 |
Денис |
pending |
800 |
2024-03-15 |
| 3 |
Вера |
cancelled |
200 |
2024-03-12 |
CASE — это способ задать кастомный порядок для строковой колонки. В алфавитном порядке cancelled шёл бы раньше paid — но нам важна не алфавитность, а смысл.
Частые ошибки новичков
1. Забыть, что без ORDER BY порядок не гарантирован. Думают: «база ведь хранит в порядке вставки». Нет, не хранит — порядок может быть любой и меняться от запроса к запросу. Нужен порядок — пиши ORDER BY.
2. ORDER BY перед FROM. Порядок частей запроса фиксированный: SELECT … FROM … WHERE … GROUP BY … HAVING … ORDER BY … LIMIT. ORDER BY всегда ближе к концу.
3. Сортировать по колонке, которой нет в SELECT. В большинстве БД это работает: можно сортировать по любой колонке таблицы, даже если её нет в выводе. Но если ты в SELECT кладёшь DISTINCT — будет ошибка, потому что DISTINCT убирает информацию, по которой нужно было бы сортировать.
4. ORDER BY 1, 2. Можно сортировать по порядковому номеру колонки в SELECT — 1 это первая, 2 вторая. Работает, но плохо читается. Лучше явно по имени.
5. ORDER BY и UNION. Если объединяешь два запроса через UNION, ORDER BY пишется только один раз в конце и применяется ко всему результату. Внутри отдельных частей UNION — нельзя.
6. Числа как строки. Если колонка типа VARCHAR хранит числа («10», «2», «100»), сортировка будет по алфавиту, а не по числам: «10», «100», «2». Лечится либо приведением типа ORDER BY CAST(col AS INTEGER), либо изначально хранить как число.
Мини-резюме
ORDER BY сортирует результат запроса.
ASC (по умолчанию) — возрастание, DESC — убывание.
- Можно сортировать по нескольким колонкам через запятую — многоуровневая сортировка.
- Можно сортировать по выражениям и функциям, не только по колонкам.
- Без
ORDER BY порядок не гарантирован.
- В сочетании с
LIMIT даёт топ-N.
- Обращай внимание на NULL — базы кладут их по-разному.
ORDER BY— это команда для сортировки результата запроса. Без неё база отдаёт строки в произвольном порядке (как ей удобнее), и для пользователя это выглядит как хаос. СORDER BYты явно говоришь: «отсортируй мне по этой колонке от меньшего к большему» (или наоборот).Аналогия: представь стопку книг на столе, кинутых как попало.
ORDER BY title— это «расставь по алфавиту названий».ORDER BY year DESC— «сначала самые новые, потом старые».Зачем нужен ORDER BY
Безsortировки SQL не даёт никаких гарантий о порядке. Один и тот же запрос два раза подряд может вернуть строки в разном порядке. Поэтому если в результате важен порядок (топ-10 продаж, новости по дате, лидерборд) —
ORDER BYобязателен.Типичные сценарии:
Базовый синтаксис
SELECT * FROM таблица ORDER BY колонка [ASC | DESC];ASC— ascending (по возрастанию). Это значение по умолчанию — можно опускать.DESC— descending (по убыванию).Пример: библиотека книг.
SELECT title, year FROM books ORDER BY year DESC;Получим список книг от самой новой к самой старой.
Пример: библиотека
Таблица
books:Запрос — отсортировать по году издания (по возрастанию):
SELECT title, year FROM books ORDER BY year;Результат:
Самая старая — сверху. Если поменять на
DESC, порядок перевернётся, самая новая будет первой.Сортировка по нескольким колонкам
Часто одной колонки мало. Например, по году издания совпадение — нужно дополнительно отсортировать по рейтингу. Просто перечисляй через запятую:
SELECT title, year, rating FROM books ORDER BY year DESC, rating DESC;Как это работает:
year DESC(новые сверху).rating DESC.Это называется «многоуровневая сортировка». Очень частая штука: «сначала по дате, внутри даты — по приоритету», «сначала по статусу, внутри статуса — по сумме».
Пример с многоуровневой сортировкой. Таблица
employees:Запрос: сначала по отделу (по алфавиту), внутри отдела — по зарплате (от большей к меньшей).
SELECT name, department, salary FROM employees ORDER BY department ASC, salary DESC;Результат:
Отделы идут по алфавиту: HR → IT → Sales. Внутри IT — Вера (150к), потом Анна и Денис (по 120к, в произвольном порядке между собой), потом и так далее.
Если хочется детерминированный порядок и у Анны с Денисом — добавь третий уровень, например по имени:
ORDER BY department ASC, salary DESC, name ASC.Сортировка по выражению
В
ORDER BYможно класть не только имена колонок, но и выражения:SELECT title, likes, views FROM posts ORDER BY likes / views DESC;Это отсортирует посты по «engagement rate» — отношению лайков к просмотрам. В таблице такой колонки нет, но база посчитает на лету.
Другой типичный сценарий — функции:
SELECT name FROM users ORDER BY LOWER(name);LOWERприводит имя к нижнему регистру для регистронезависимой сортировки.Топ-N: ORDER BY + LIMIT
Классическая комбинация. Чтобы получить «топ-3 поста по лайкам», нужно сначала отсортировать, потом обрезать:
SELECT title, likes FROM posts ORDER BY likes DESC LIMIT 3;Сначала
ORDER BY likes DESCставит самые залайканные сверху, потомLIMIT 3берёт первые три. БезORDER BYLIMIT 3вернёт три случайные строки — это типичный баг новичков.NULL в сортировке
Если в колонке есть
NULL-значения, базы по-разному решают, куда их положить:ASC— NULL в конце, приDESC— в начале.ASC— NULL в начале, приDESC— в конце.Если важно явно — в PostgreSQL есть
NULLS FIRST/NULLS LAST:SELECT title, published_at FROM posts ORDER BY published_at DESC NULLS LAST;Получим: сначала свежие посты, в самом конце — те, у которых даты публикации ещё нет (черновики). В MySQL такого синтаксиса нет, нужно делать через выражение:
ORDER BY published_at IS NULL, published_at DESC.Большой пример: до и после
Таблица
orders:Запрос: «сначала оплаченные, потом ожидающие, потом отменённые. Внутри каждой группы — самые новые сверху, при равенстве дат — большие суммы первые».
SELECT id, customer, status, amount, created_at FROM orders ORDER BY CASE status WHEN 'paid' THEN 1 WHEN 'pending' THEN 2 WHEN 'cancelled' THEN 3 END, created_at DESC, amount DESC;Результат:
CASE— это способ задать кастомный порядок для строковой колонки. В алфавитном порядкеcancelledшёл бы раньшеpaid— но нам важна не алфавитность, а смысл.Частые ошибки новичков
1. Забыть, что без ORDER BY порядок не гарантирован. Думают: «база ведь хранит в порядке вставки». Нет, не хранит — порядок может быть любой и меняться от запроса к запросу. Нужен порядок — пиши
ORDER BY.2. ORDER BY перед FROM. Порядок частей запроса фиксированный:
SELECT … FROM … WHERE … GROUP BY … HAVING … ORDER BY … LIMIT.ORDER BYвсегда ближе к концу.3. Сортировать по колонке, которой нет в SELECT. В большинстве БД это работает: можно сортировать по любой колонке таблицы, даже если её нет в выводе. Но если ты в SELECT кладёшь
DISTINCT— будет ошибка, потому что DISTINCT убирает информацию, по которой нужно было бы сортировать.4.
ORDER BY 1, 2. Можно сортировать по порядковому номеру колонки в SELECT —1это первая,2вторая. Работает, но плохо читается. Лучше явно по имени.5. ORDER BY и UNION. Если объединяешь два запроса через
UNION,ORDER BYпишется только один раз в конце и применяется ко всему результату. Внутри отдельных частей UNION — нельзя.6. Числа как строки. Если колонка типа
VARCHARхранит числа («10», «2», «100»), сортировка будет по алфавиту, а не по числам: «10», «100», «2». Лечится либо приведением типаORDER BY CAST(col AS INTEGER), либо изначально хранить как число.Мини-резюме
ORDER BYсортирует результат запроса.ASC(по умолчанию) — возрастание,DESC— убывание.ORDER BYпорядок не гарантирован.LIMITдаёт топ-N.