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. Разберём в следующем уроке.