SQLLab
Все статьи

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

ORDER BY в SQL: сортировка по одной и нескольким колонкам, ASC/DESC, NULLS FIRST/LAST, сортировка по выражению. Примеры с пояснениями.

22 марта 2026 г.·3 мин чтения·

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

Базовый синтаксис

SELECT name, salary FROM employees ORDER BY salary;         -- по возрастанию
SELECT name, salary FROM employees ORDER BY salary DESC;    -- по убыванию
SELECT name, salary FROM employees ORDER BY salary ASC;     -- явно по возрастанию

По умолчанию — ASC (ascending, возрастание).

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

-- Сначала по отделу, внутри — по зарплате убыванию
SELECT name, department, salary
FROM employees
ORDER BY department ASC, salary DESC;

Каждая колонка сортируется независимо и может иметь своё направление.

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

-- Вместо названия — порядковый номер из SELECT
SELECT name, department, salary FROM employees ORDER BY 3 DESC;
-- 3 = salary

Удобно в интерактивных запросах, но в продакшн-коде лучше писать явно — сложнее читать.

Сортировка по выражению

-- По длине имени
SELECT name FROM users ORDER BY LENGTH(name);

-- По вычисляемому полю
SELECT product, price, quantity, price * quantity AS total
FROM order_items
ORDER BY price * quantity DESC;

-- По псевдониму из SELECT
SELECT product, price * quantity AS total
FROM order_items
ORDER BY total DESC;

NULL в сортировке

-- По умолчанию в PostgreSQL NULL идут последними при ASC, первыми при DESC
SELECT name, score FROM users ORDER BY score DESC;
-- NULL окажутся первыми

-- Явное управление
SELECT name, score FROM users ORDER BY score DESC NULLS LAST;
SELECT name, score FROM users ORDER BY score ASC  NULLS FIRST;

CASE WHEN в ORDER BY

-- Кастомный порядок: сначала 'active', потом 'pending', потом остальные
SELECT name, status FROM users
ORDER BY
    CASE status
        WHEN 'active'  THEN 1
        WHEN 'pending' THEN 2
        ELSE 3
    END;
-- VIP клиенты сверху, потом по алфавиту
SELECT name, tier FROM customers
ORDER BY
    CASE WHEN tier = 'VIP' THEN 0 ELSE 1 END,
    name;

ORDER BY с LIMIT

-- Топ-10 по выручке
SELECT user_id, SUM(amount) AS revenue
FROM orders
GROUP BY user_id
ORDER BY revenue DESC
LIMIT 10;
-- Пагинация
SELECT * FROM products
ORDER BY created_at DESC
LIMIT 20 OFFSET 40;  -- страница 3 (по 20 на странице)

ORDER BY в подзапросах

ORDER BY в подзапросе не гарантирует порядок во внешнем запросе:

-- Порядок здесь определяется внешним ORDER BY, не внутренним
SELECT * FROM (
    SELECT * FROM orders ORDER BY amount DESC  -- не влияет на итог
) sub
ORDER BY created_at;  -- этот ORDER BY определяет результат

Производительность

ORDER BY может быть дорогой операцией на больших таблицах — базе нужно отсортировать весь результат. Индекс по колонке сортировки может значительно ускорить запрос.

-- Если часто делаете ORDER BY created_at DESC — нужен индекс
CREATE INDEX idx_orders_created_at ON orders(created_at DESC);

Порядок выполнения

ORDER BY выполняется почти последним:

  1. FROM
  2. WHERE
  3. GROUP BY
  4. HAVING
  5. SELECT
  6. ORDER BY
  7. LIMIT

Поэтому в ORDER BY можно использовать псевдонимы из SELECT:

SELECT user_id, COUNT(*) AS orders_count
FROM orders
GROUP BY user_id
ORDER BY orders_count DESC;  -- псевдоним работает

Похожие статьи

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

Тренажёр с реальными задачами — бесплатно и без регистрации

Открыть тренажёр →