БэкендData и ИИSQL

SQL ORDER BY для начинающих: сортировка по одному и нескольким столбцам

Учимся сортировать строки SQL через ORDER BY: ASC, DESC, несколько столбцов, NULL, LIMIT и устойчивый порядок на понятной таблице курсов.

Кодик

Автор

6 мин чтения

Чтобы отсортировать результат SQL-запроса, добавьте в конце ORDER BY column ASC для возрастания или ORDER BY column DESC для убывания. Без ORDER BY база не обещает порядок строк, даже если вчера они выглядели отсортированными. Для одинаковых значений добавляйте второй критерий, обычно уникальный id, а положение NULL задавайте явно, когда оно важно интерфейсу или отчёту.

Запрос вернул пять курсов, но дорогой оказался между дешёвыми, а после добавления новой записи порядок изменился. Таблица физически хранит данные не как аккуратный список для экрана. SQL формирует множество строк, и только ORDER BY превращает его в предсказуемую последовательность для пользователя.

1Выбираем критерий

Решаем, что значит «сначала»: цена, дата, имя, рейтинг или несколько полей.

2Задаём направление

Используем ASC для меньшего к большему и DESC для обратного порядка.

3Устраняем ничьи

Добавляем следующий столбец и уникальный id, чтобы одинаковые значения не перемешивались.

Как работает ORDER BY и почему порядок без него случайный

ORDER BY применяется к строкам результата после отбора и вычисления выбранных выражений. По умолчанию направление ASC, но его полезно писать явно в учебном и командном коде. Без этой части СУБД вправе выбрать любой план выполнения и вернуть строки в удобном ей порядке. Индекс, свежая вставка или другой фильтр могут незаметно его изменить.

ЗадачаORDER BYПервая строка
Самая низкая ценаprice ASCМинимальная цена
Самая высокая ценаprice DESCМаксимальная цена
Новое сначалаcreated_at DESCСамая поздняя дата
По алфавитуtitle ASCЗависит от collation
Стабильно при равенствеprice ASC, id ASCМеньшая цена, затем меньший id

Схема сортировки строк SQL оператором ORDER BY ASC и DESC
Направление относится к каждому критерию, а не ко всей таблице навсегда.

Наблюдаемый порядок не является гарантией. Если в запросе нет ORDER BY, приложение не должно полагаться на порядок строк, полученный в одном тестовом запуске.

Пишем запросы с 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 по возрастанию.

Каскад сортировки SQL по цене рейтингу и идентификатору
Следующий столбец вступает в работу только при равенстве предыдущего.

Что происходит с 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Предсказуемые ничьиПагинация и рейтинг
LIMIT без ORDER BY не означает последние или лучшие. Он просто ограничивает текущий результат. Сначала задайте критерий, затем берите первые N строк.

Практика: строим витрину курсов с понятным порядком

Создайте пять строк: две с ценой 0, две с одинаковым рейтингом и одну с NULL вместо цены. Такой набор сразу обнаруживает слабые места запроса. Задача витрины: бесплатные и дешёвые курсы должны идти первыми, неизвестная цена последней, а одинаковую цену разрешает рейтинг по убыванию и затем id.

Три запроса для проверки
  1. Добавьте курсы с id от 1 до 5, ценами 0, 1200, 0, NULL, 800 и несколькими одинаковыми рейтингами.
  2. Выполните ORDER BY price ASC NULLS LAST, rating DESC, id ASC и запишите ожидаемый порядок id до запуска.
  3. Поменяйте ASC на DESC только у price и объясните, куда переместятся бесплатные записи.
  4. Оставьте один ORDER BY rating DESC и несколько раз измените данные. Заметьте, что ничьи не имеют заданного порядка.
  5. Добавьте id ASC, затем LIMIT 3. Теперь первая страница воспроизводится однозначно.
  6. Проверьте отдельный запрос названий и сравните обычный title с lower(title) на разном регистре.
Что должно стать предсказуемым
  • Строка с NULL не смешивается с известными ценами и оказывается в выбранном конце списка.
  • Одинаковые цены сравниваются по рейтингу, а полные ничьи окончательно решает id.
  • LIMIT возвращает одну и ту же первую тройку, пока значения критериев не изменились.

Порядок выполнения ORDER BY NULLS LAST и LIMIT
Сначала формируется полный порядок, затем LIMIT берёт первые строки.

Какие ошибки делают сортировку неверной или нестабильной

ORDER BY легко написать синтаксически верно и получить логически неверный результат. Числа, сохранённые как текст, сортируются лексикографически: «100» может оказаться раньше «20». Форматированные даты в строках тоже не обязательно совпадают с хронологией. Ещё одна проблема появляется при пагинации, если критерий не уникален.

Числа хранятся как TEXT

Сортировка сравнивает символы, а не величины. Исправьте тип столбца; постоянный CAST маскирует плохую модель.

DESC написан один раз в конце списка

Направление относится к конкретному выражению. Указывайте его после каждого столбца, где нужен обратный порядок.

Нет критерия для одинаковых значений

При LIMIT и пагинации строки могут прыгать между страницами. Добавьте уникальный id последним ключом.

Положение NULL оставлено неявным

Интерфейс получает записи без цены не там, где ожидалось. Задайте NULLS FIRST или LAST в поддерживающей это СУБД.

Сортировка выполняется в приложении после LIMIT

Вы уже получили случайную часть данных. Сортируйте в SQL до ограничения результата.

Проговорите запрос обычной фразой. «Сначала цена по росту без NULL, среди одинаковой цены рейтинг по убыванию, затем id» сразу показывает порядок критериев и направлений. Технические детали сверены с официальной документацией PostgreSQL по ORDER BY.
Короткие ответы
Какое направление используется по умолчанию?

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.