SQLучебникдля начинающихORDER BYLIMITDISTINCTчасть-3

SQL с нуля. Часть 3: ORDER BY, LIMIT, DISTINCT, OFFSET

2026-06-02 7 мин

Это часть 3 из 10 учебника «SQL с нуля для аналитика». Содержание серии в конце поста. ← Часть 2


TL;DR: ORDER BY сортирует результат (ASC по возрастанию по умолчанию, DESC по убыванию). LIMIT N берёт только первые N строк. OFFSET N пропускает первые N. DISTINCT оставляет только уникальные значения. Эти 4 ключевых слова решают типичные задачи: «топ-10 покупателей», «уникальные страны», «вторая страница».

В этой части:


Как отсортировать результат?

ORDER BY сортирует строки:
-- По возрастанию (по умолчанию)
SELECT email, created_at
FROM users
ORDER BY created_at;

-- По убыванию (новейшие сверху)
SELECT email, created_at
FROM users
ORDER BY created_at DESC;

ASC = ascending (по возрастанию), DESC = descending (по убыванию). Без указания — ASC.

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

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

-- Сначала по стране (по алфавиту), потом по выручке (от большей)
SELECT country, user_id, revenue
FROM users_revenue
ORDER BY country ASC, revenue DESC;

Результат: внутри каждой страны — топ-выручка сверху.

Как взять только первые N строк?

LIMIT N ограничивает количество результата:
-- Топ-10 покупателей по выручке
SELECT user_id, SUM(amount) AS total
FROM orders
GROUP BY user_id
ORDER BY total DESC
LIMIT 10;

(GROUP BY разберём в Части 4).

LIMIT без ORDER BY возвращает любые N строк (порядок не гарантирован). Это частая ошибка.
Например, типичные топ-N кейсы аналитика: топ-10 продуктов по выручке, топ-50 клиентов по LTV, топ-5 каналов с худшей конверсией. Все через ORDER BY metric DESC LIMIT N.

Как делать пагинацию?

OFFSET N пропускает первые N строк:
-- Первая страница (10 строк)
SELECT email FROM users ORDER BY id LIMIT 10 OFFSET 0;

-- Вторая страница (строки 11-20)
SELECT email FROM users ORDER BY id LIMIT 10 OFFSET 10;

-- Третья страница (21-30)
SELECT email FROM users ORDER BY id LIMIT 10 OFFSET 20;

Формула: OFFSET = (page - 1) * page_size.

Подвох: OFFSET медленный на больших таблицах. БД всё равно читает первые OFFSET строк, потом отбрасывает. Для page 1000 на 10М-таблице — секунды. Альтернатива — keyset pagination (через WHERE по id), но это уже advanced. Подробнее в SQL antipatterns.

Как получить уникальные значения?

DISTINCT оставляет только уникальные строки:
-- Все страны, в которых есть пользователи
SELECT DISTINCT country FROM users;

-- Уникальные пары (страна, статус)
SELECT DISTINCT country, status FROM orders;
DISTINCT работает по всем выбранным колонкам, не только по первой.
Типичный случай: после миграции с MS SQL на PostgreSQL обнаруживаются дубли user_id в events (legacy session-tracking генерировал случайные UUID). SELECT DISTINCT user_id показывает реальное количество уникальных пользователей.

DISTINCT vs GROUP BY — что выбрать?

Они часто дают одинаковый результат:

-- Эквивалентны
SELECT DISTINCT country FROM users;
SELECT country FROM users GROUP BY country;

Разница:

КритерийDISTINCTGROUP BY
Простой случайКорочеМногословнее
Нужны агрегаты (COUNT, SUM)Не работаетИдеально
PerformanceЧаще равныИногда быстрее

Правило: для простых уникальных — DISTINCT. Для агрегатов — GROUP BY. Подробнее GROUP BY в Части 4.

Какие 4 типичные ошибки с ORDER BY и LIMIT?

SELECT user_id, last_login
FROM users
ORDER BY last_login DESC NULLS LAST;

Частые вопросы про ORDER BY, LIMIT, DISTINCT

Как взять случайную строку?

ORDER BY RANDOM() LIMIT 1 (PG) или ORDER BY RAND() LIMIT 1 (MySQL). Медленно на больших таблицах — БД сортирует всё, потом берёт 1. Для production — TABLESAMPLE.

Что такое NULLS FIRST / NULLS LAST?

Управление порядком NULL в результате. PostgreSQL default: NULL последние при ASC, первые при DESC. Явно: ORDER BY col ASC NULLS FIRST.

Можно ли в LIMIT использовать переменную?

В standalone SQL — нет. В коде приложения (Python/JS) — да, через параметризацию. В dbt — через Jinja {{ var('page_size') }}.

LIMIT 0 — что вернёт?

Пустой результат, но БД всё равно подготавливает план. Иногда используется для проверки схемы запроса без исполнения. Лучше EXPLAIN для этого.

DISTINCT медленнее GROUP BY?

В современных PG/CH — обычно равны. Оптимизатор для DISTINCT по сути делает GROUP BY под капотом.

Что дальше?

В Части 4 — самая важная часть для аналитика: агрегатные функции (COUNT, SUM, AVG, MIN, MAX) и GROUP BY. Без этого никаких метрик не посчитать.

Сейчас открой SQL-тренажёр — попробуй написать запрос «топ-5 пользователей по выручке» с ORDER BY + LIMIT.

В Pro — безлимит мок-собесов на AI-интервью + 491 SQL-задача + 612 тестовых заданий + 50+ блог-постов.


Навигация по учебнику

← Часть 2 | Часть 3: ORDER BY, LIMIT, DISTINCT | Часть 4 →

Содержание серии: 1 · 2 · 3 · 4 · 5 · 6 · 7 · 8 · 9 · 10

← Вернуться к оглавлению

Источники

SQL-тренажёр
Практика ORDER BY на реальном PostgreSQL 16. 491 задача, первые 5 бесплатно.
Открыть тренажёр →