ORDER BY: сортировка результатов

ORDER BY: сортировка результатов

В предыдущем уроке вы научились фильтровать строки с помощью WHERE и логических операторов. Но отфильтрованные строки возвращаются в произвольном порядке — именно в том порядке, в котором СУБД обходит страницы данных. Для пользователя список сотрудников в случайном порядке — неудобен. Нужна сортировка: по алфавиту, по дате, по цене. Для этого существует клауза ORDER BY.

Синтаксис ORDER BY

ORDER BY добавляется в конце запроса, после WHERE:

SELECT колонки
FROM   таблица
WHERE  условие
ORDER BY колонка [ASC | DESC];

ASC (ascending) — по возрастанию, от меньшего к большему. Это значение по умолчанию: если не указать ни ASC, ни DESC, сортировка будет по возрастанию.

DESC (descending) — по убыванию, от большего к меньшему.

Пример — список сотрудников по зарплате от меньшей к большей:

SELECT name, department, salary
FROM   employees
ORDER BY salary ASC;

Результат:

name   | department  | salary
-------+-------------+--------
Гриша  | Дизайн      | 75000
Вера   | Разработка  | 85000
Анна   | Разработка  | 90000
Дина   | Разработка  | 95000
Борис  | Менеджмент  | 110000

Тот же список по убыванию:

SELECT name, department, salary
FROM   employees
ORDER BY salary DESC;

Результат: Борис, Дина, Анна, Вера, Гриша.

Сортировка по строковым колонкам

Строки сортируются в лексикографическом (алфавитном) порядке. ASC — от А до Я (или A до Z), DESC — в обратном направлении.

SELECT name, department
FROM   employees
ORDER BY name ASC;

Результат: Анна, Борис, Вера, Гриша, Дина — по алфавиту.

Нюанс: сортировка строк чувствительна к локали (locale) базы данных. В PostgreSQL стандартная локаль для русского текста — ru_RU.UTF-8. Если база настроена на неё, русские буквы сортируются правильно. Если используется локаль C или POSIX, русские символы могут сортироваться неожиданно. На практике это редко проблема — большинство баз настроены корректно.

Сортировка по нескольким колонкам

ORDER BY принимает несколько колонок, разделённых запятыми. Сортировка применяется слева направо: сначала по первой колонке, затем по второй — для строк, где первая колонка одинакова.

SELECT name, department, salary
FROM   employees
ORDER BY department ASC, salary DESC;

Результат:

name   | department  | salary
-------+-------------+--------
Гриша  | Дизайн      | 75000   ← один сотрудник в отделе
Борис  | Менеджмент  | 110000  ← один сотрудник в отделе
Дина   | Разработка  | 95000   ← внутри Разработки — по убыванию зарплаты
Анна   | Разработка  | 90000
Вера   | Разработка  | 85000

Сначала отделы по алфавиту (Дизайн → Менеджмент → Разработка). Внутри каждого отдела — по убыванию зарплаты.

Для каждой колонки в ORDER BY можно задавать своё направление:

ORDER BY department ASC, salary DESC, name ASC

Три правила: отдел по возрастанию → зарплата по убыванию → имя по возрастанию (для одинаковых зарплат).

Проверь себя: в каком порядке отсортирует ORDER BY department DESC, name ASC для нашей таблицы?

ORDER BY с WHERE

WHERE и ORDER BY работают вместе — фильтрация происходит сначала, сортировка — потом:

SELECT name, salary
FROM   employees
WHERE  department = 'Разработка'
ORDER BY salary DESC;

Логика: берём только разработчиков (WHERE), затем сортируем по зарплате убывающе (ORDER BY).

name  | salary
------+--------
Дина  | 95000
Анна  | 90000
Вера  | 85000

ORDER BY по вычисляемому выражению

В ORDER BY можно использовать выражения, а не только имена колонок:

SELECT name, salary
FROM   employees
ORDER BY salary * 12 DESC;   -- годовая зарплата по убыванию

Это позволяет сортировать по значению, которого нет в таблице напрямую.

Ещё один способ — использовать псевдоним из SELECT. В отличие от WHERE, в ORDER BY псевдонимы работают. Это исключение из правила «SELECT выполняется позже»: PostgreSQL обрабатывает ORDER BY после SELECT и может видеть псевдонимы.

SELECT name,
       salary * 12 AS annual_salary
FROM   employees
ORDER BY annual_salary DESC;   -- псевдоним работает в ORDER BY

Это удобно: не нужно повторять выражение в ORDER BY.

ORDER BY и NULL

Что происходит с NULL-значениями при сортировке? По умолчанию в PostgreSQL NULL считается больше любого значения. При ASC-сортировке NULL уходит в конец; при DESC — в начало.

Если хотите явно управлять поведением NULL, используйте NULLS FIRST или NULLS LAST:

SELECT name, score
FROM   students
ORDER BY score DESC NULLS LAST;   -- NULL в конце, остальные по убыванию
ORDER BY score ASC NULLS FIRST;   -- NULL в начале, остальные по возрастанию

Это стандартная SQL-фича, работающая в PostgreSQL. SQLite также поддерживает NULLS FIRST / LAST.

ORDER BY по номеру колонки

В SQL есть синтаксический сахар: в ORDER BY можно указать номер позиции колонки из SELECT-списка вместо её имени:

SELECT name, department, salary
FROM   employees
ORDER BY 3 DESC;   -- 3 = salary (третья колонка в SELECT)

Это сортирует по salary DESC. Формально работает, но в коде продакшн-уровня такой стиль не рекомендуется: если порядок колонок в SELECT изменится, сортировка молча станет другой — без ошибки. Именуйте колонки явно.

Гарантированный порядок

Важный момент для понимания: без ORDER BY порядок строк в результате не гарантирован. Разные запросы к одной таблице могут вернуть строки в разном порядке, даже если данные не изменялись. СУБД вольна выбирать любой порядок обхода данных — в зависимости от плана выполнения запроса.

Если вам важен порядок — всегда добавляйте ORDER BY. Не полагайтесь на «естественный» порядок.

Практический пример: каталог товаров

Задача: вывести товары магазина в наличии, отсортированные по категории и цене от меньшей к большей:

SELECT name,
       category,
       price,
       stock
FROM   products
WHERE  stock > 0
ORDER BY category ASC,
         price    ASC;

Сначала фильтруем товары в наличии (WHERE stock > 0), затем сортируем по категории и внутри категории — по возрастанию цены. Покупатели увидят аккуратный каталог с самыми дешёвыми товарами в каждой категории наверху.

Типичные ошибки

1. ORDER BY до WHERE:

SELECT * FROM employees ORDER BY salary WHERE department = 'IT';  -- ошибка!

Правильный порядок: FROM → WHERE → ORDER BY.

2. Ожидание гарантированного порядка без ORDER BY:

SELECT * FROM employees;  -- порядок случаен, не полагайтесь на него

3. Ссылка на псевдоним в WHERE, а не в ORDER BY:

SELECT salary * 12 AS annual
FROM   employees
WHERE  annual > 1000000   -- ошибка: псевдоним недоступен в WHERE
ORDER BY annual DESC;     -- ок: псевдоним работает в ORDER BY

ORDER BY и производительность

На небольших таблицах ORDER BY практически мгновенен. На больших (миллионы строк) сортировка требует ресурсов — СУБД должна обработать все отфильтрованные строки, расположить их в нужном порядке, и только потом вернуть результат.

Если в таблице есть индекс на колонку сортировки, PostgreSQL может использовать его для «бесплатной» сортировки без дополнительного прохода. Если индекса нет — СУБД выполняет сортировку в памяти или на диске. Детали индексов разберём в модуле 10; пока просто знайте, что ORDER BY по неиндексированным колонкам на больших таблицах — потенциально медленная операция.

Разница между ASC и DESC в разных контекстах

Выбор ASC или DESC зависит от задачи:

  • Список по алфавиту (имена, названия товаров): ASC — привычный порядок А–Я
  • Топ N самых дорогих/прибыльных/популярных: DESC — самые большие значения сначала
  • Последние события (логи, заказы, сообщения): DESC по дате — самые новые сначала
  • Хронологический порядок (история): ASC по дате — от старых к новым

Например, вывести последние 5 заказов (когда освоим LIMIT в следующем уроке):

SELECT order_id, created_at, total_amount
FROM   orders
ORDER BY created_at DESC;

Итоговая структура запроса

Сейчас мы изучили все клаузы модуля 2 и модуля 3. Полная структура запроса выглядит так:

SELECT name, salary * 12 AS annual_salary
FROM   employees
WHERE  department = 'IT' AND salary > 50000
ORDER BY annual_salary DESC;

Каждая часть добавляется в строго определённом месте:

SELECT  ... — что возвращаем
FROM    ... — откуда берём
WHERE   ... — фильтр строк
ORDER BY ... — сортировка

Клаузы LIMIT и OFFSET будут в конце — после ORDER BY. Об этом — в следующем уроке.

Краткий итог

  • ORDER BY колонка ASC — по возрастанию (умолчание); DESC — по убыванию
  • Несколько колонок: ORDER BY col1 ASC, col2 DESC — сначала по первой, затем по второй
  • ORDER BY выполняется после WHERE: сначала фильтрация, затем сортировка
  • Псевдонимы из SELECT работают в ORDER BY (в отличие от WHERE)
  • NULL по умолчанию в конце при ASC; управляйте через NULLS FIRST / LAST
  • Без ORDER BY порядок строк не гарантирован
  • DESC по временной колонке — «самые новые сначала»; ASC — хронологически

Что дальше

Вы умеете сортировать результат. Часто нужно ещё и ограничить количество строк — например, показать топ-10 самых дорогих товаров или пагинировать список. Для этого существует клауза LIMIT — и дополняющий её OFFSET. Разберём в следующем уроке.

Попробуйте интерактивную версию

Практические задачи, квизы и AI-наставник — бесплатный старт без карты

Перейти к практике