Чтобы отсортировать результат SQL-запроса, добавьте в конце ORDER BY column ASC для возрастания или ORDER BY column DESC для убывания. Без ORDER BY база не обещает порядок строк, даже если вчера они выглядели отсортированными. Для одинаковых значений добавляйте второй критерий, обычно уникальный id, а положение NULL задавайте явно, когда оно важно интерфейсу или отчёту.
Запрос вернул пять курсов, но дорогой оказался между дешёвыми, а после добавления новой записи порядок изменился. Таблица физически хранит данные не как аккуратный список для экрана. SQL формирует множество строк, и только ORDER BY превращает его в предсказуемую последовательность для пользователя.
Решаем, что значит «сначала»: цена, дата, имя, рейтинг или несколько полей.
Используем ASC для меньшего к большему и DESC для обратного порядка.
Добавляем следующий столбец и уникальный id, чтобы одинаковые значения не перемешивались.
Как работает ORDER BY и почему порядок без него случайный
ORDER BY применяется к строкам результата после отбора и вычисления выбранных выражений. По умолчанию направление ASC, но его полезно писать явно в учебном и командном коде. Без этой части СУБД вправе выбрать любой план выполнения и вернуть строки в удобном ей порядке. Индекс, свежая вставка или другой фильтр могут незаметно его изменить.
| Задача | ORDER BY | Первая строка |
|---|---|---|
| Самая низкая цена | price ASC | Минимальная цена |
| Самая высокая цена | price DESC | Максимальная цена |
| Новое сначала | created_at DESC | Самая поздняя дата |
| По алфавиту | title ASC | Зависит от collation |
| Стабильно при равенстве | price ASC, id ASC | Меньшая цена, затем меньший id |

Направление относится к каждому критерию, а не ко всей таблице навсегда.
Пишем запросы с ASC, DESC и несколькими критериями
Критерии перечисляются слева направо. Сначала база сравнивает первый столбец. Второй используется только для строк, у которых первое значение одинаково, третий разрешает оставшиеся ничьи. Направление задаётся отдельно для каждого критерия: например, сначала максимальный рейтинг, а среди равных названия по алфавиту.
CREATE TABLE courses (
id INTEGER PRIMARY KEY,
title TEXT NOT NULL,
level TEXT NOT NULL,
price INTEGER,
rating NUMERIC(2, 1)
);
-- Дешёвые курсы сначала, ничьи решает id
SELECT id, title, price
FROM courses
ORDER BY price ASC, id ASC;
-- Лучший рейтинг сначала, затем название
SELECT title, level, rating
FROM courses
WHERE level = 'beginner'
ORDER BY rating DESC, title ASC;- Сначала остаются только курсы уровня beginner.
- Более высокий rating располагается раньше более низкого.
- Если rating одинаков, строки сортируются по title по возрастанию.

Следующий столбец вступает в работу только при равенстве предыдущего.
Что происходит с NULL, текстом и LIMIT
NULL означает неизвестное значение и требует отдельного внимания. В PostgreSQL для него можно явно написать NULLS FIRST или NULLS LAST; значения по умолчанию зависят от направления. Текст сортируется по правилам сопоставления базы, поэтому регистр и язык могут давать неожиданный для человека порядок. LIMIT выбирает первые строки уже после сортировки, если ORDER BY записан правильно.
| Конструкция | Результат | Когда нужна |
|---|---|---|
price ASC NULLS LAST | Известные цены по росту, NULL в конце | Каталог с неопределённой ценой |
rating DESC NULLS LAST | Высокий рейтинг первым, нет оценки в конце | Рейтинг материалов |
ORDER BY lower(title) | Сортировка по приведённому регистру | Простой регистронезависимый список |
ORDER BY created_at DESC LIMIT 10 | Десять новых строк | Лента последних записей |
ORDER BY score DESC, id ASC | Предсказуемые ничьи | Пагинация и рейтинг |
Практика: строим витрину курсов с понятным порядком
Создайте пять строк: две с ценой 0, две с одинаковым рейтингом и одну с NULL вместо цены. Такой набор сразу обнаруживает слабые места запроса. Задача витрины: бесплатные и дешёвые курсы должны идти первыми, неизвестная цена последней, а одинаковую цену разрешает рейтинг по убыванию и затем id.
- Добавьте курсы с id от 1 до 5, ценами
0, 1200, 0, NULL, 800и несколькими одинаковыми рейтингами. - Выполните
ORDER BY price ASC NULLS LAST, rating DESC, id ASCи запишите ожидаемый порядок id до запуска. - Поменяйте ASC на DESC только у price и объясните, куда переместятся бесплатные записи.
- Оставьте один
ORDER BY rating DESCи несколько раз измените данные. Заметьте, что ничьи не имеют заданного порядка. - Добавьте
id ASC, затемLIMIT 3. Теперь первая страница воспроизводится однозначно. - Проверьте отдельный запрос названий и сравните обычный
titleсlower(title)на разном регистре.
- Строка с NULL не смешивается с известными ценами и оказывается в выбранном конце списка.
- Одинаковые цены сравниваются по рейтингу, а полные ничьи окончательно решает id.
- LIMIT возвращает одну и ту же первую тройку, пока значения критериев не изменились.

Сначала формируется полный порядок, затем LIMIT берёт первые строки.
Какие ошибки делают сортировку неверной или нестабильной
ORDER BY легко написать синтаксически верно и получить логически неверный результат. Числа, сохранённые как текст, сортируются лексикографически: «100» может оказаться раньше «20». Форматированные даты в строках тоже не обязательно совпадают с хронологией. Ещё одна проблема появляется при пагинации, если критерий не уникален.
Сортировка сравнивает символы, а не величины. Исправьте тип столбца; постоянный CAST маскирует плохую модель.
Направление относится к конкретному выражению. Указывайте его после каждого столбца, где нужен обратный порядок.
При LIMIT и пагинации строки могут прыгать между страницами. Добавьте уникальный id последним ключом.
Интерфейс получает записи без цены не там, где ожидалось. Задайте NULLS FIRST или LAST в поддерживающей это СУБД.
Вы уже получили случайную часть данных. Сортируйте в SQL до ограничения результата.
Какое направление используется по умолчанию?
ASC, то есть по возрастанию.
Зачем второй столбец в ORDER BY?
Он сортирует строки, у которых значение первого критерия одинаково.
Гарантирован ли порядок без ORDER BY?
Нет. Наблюдаемый порядок может измениться из-за плана запроса и данных.
Почему LIMIT нужно сочетать с ORDER BY?
Иначе база ограничит неопределённо упорядоченный набор и понятия «первые» не будет.
Как поместить неизвестные цены в конец PostgreSQL?
Использовать ORDER BY price ASC NULLS LAST.
Базовые запросы удобно отработать в курсе SQL: меняйте один критерий и до запуска прогнозируйте порядок строк. Так ORDER BY быстро превращается из команды в понятное правило.
Продолжите статьёй SQL для новичков, разберите SELECT, INSERT, UPDATE и DELETE, а количество строк научитесь получать в материале про SQL COUNT.