Урок 2.7: Все вместе: WHERE, ORDER BY и LIMIT
К этому моменту мы научились фильтровать строки (WHERE), сортировать их (ORDER BY) и ограничивать количество результатов (LIMIT). В реальных сценариях вы почти всегда будете использовать эти операторы вместе, чтобы получить именно те данные, которые вам нужны.
Порядок операторов
В SQL существует строгий порядок расположения этих операторов в тексте запроса. Если вы поставите их в неправильном порядке, база данных выдаст ошибку.
Ниже показана правильная последовательность только для тех операторов, которые мы уже изучили в этом модуле. Полный порядок частей SQL-запроса шире и будет пополнятся по мере изучения новых конструкций языка.
Правильная последовательность в тексте запроса:
SELECT(Какие столбцы?)FROM(Какая таблица?)WHERE(Сначала фильтруем строки)ORDER BY(Сортируем отфильтрованные строки)LIMIT(Берем первые X результатов из отсортированного списка)OFFSET(Пропускаем X строк, если необходимо)
Важно: этот порядок описывает именно то, как вы пишете запрос, а не логический порядок его выполнения. Логически SQL обрабатывает части запроса иначе.
Логический порядок выполнения
Когда вы запускаете комбинированный запрос, база данных концептуально обрабатывает его следующим образом:
- Сначала определяется источник данных из
FROM. - Затем применяются условия фильтрации из
WHERE. - После этого формируется список столбцов из
SELECT. - Далее результат сортируется по правилам
ORDER BY. - В конце сначала применяется
OFFSET, чтобы пропустить строки при необходимости, а затемLIMIT, чтобы вернуть нужную часть уже отсортированных строк.
Именно поэтому WHERE не может ссылаться на псевдонимы из SELECT: на этапе фильтрации список выбираемых столбцов еще логически не сформирован.
Примеры
Пример 1: 5 самых коротких дешевых фильмов
В этом примере мы сначала фильтруем фильмы по стоимости замены, затем сортируем их по длительности и, наконец, ограничиваем количество результатов.
SELECT title, length, replacement_cost
FROM film
WHERE replacement_cost < 20.00
ORDER BY length ASC
LIMIT 5;
Пример 2: Последние длительные аренды
Этот запрос находит 10 самых недавних аренд, которые длились более 5 дней.
SELECT rental_id, rental_date, return_date
FROM rental
WHERE return_date - rental_date > 5
ORDER BY rental_date DESC
LIMIT 10;
Пример 3: Поиск конкретных актеров
Найти первых 3 актеров, чья фамилия начинается на 'B', отсортированных по имени в алфавитном порядке.
SELECT first_name, last_name
FROM actor
WHERE last_name LIKE 'B%'
ORDER BY first_name
LIMIT 3;
Пагинация с WHERE и ORDER BY
В предыдущем уроке мы рассмотрели базовую пагинацию с использованием LIMIT и OFFSET. В реальных приложениях вы обычно перемещаетесь по отфильтрованному и отсортированному списку.
Почему для пагинации нужны WHERE и ORDER BY?
- Фильтрация: Пользователи обычно хотят видеть определенное подмножество данных (например, «Активные» товары или фильмы жанра «Комедия»).
- Согласованность: Без
ORDER BYбаза данных может возвращать строки в разном порядке при каждом переходе на следующую страницу, из-за чего некоторые элементы могут появиться дважды, а другие — вообще исчезнуть из вывода.
Формула пагинации
Для реализации пагинации для «Страницы N» с количеством результатов «S» на страницу:
LIMIT SOFFSET (N - 1) * S
Комплексный пример: Страница 2 актеров на 'A'
Если мы хотим показать вторую страницу (5 результатов на страницу) актеров, чье имя начинается на 'A', отсортированных по фамилии:
SELECT first_name, last_name
FROM actor
WHERE first_name LIKE 'A%'
ORDER BY last_name
LIMIT 5 OFFSET 5; -- Страница 2: пропустить 5, взять 5
Ключевые выводы этого урока:
- Соблюдайте строгий синтаксический порядок:
WHERE->ORDER BY->LIMIT. - Условия оператора
WHEREприменяются до того, как происходит сортировка и ограничение. - Эта комбинация является основой для большинства отчетов и списков «топ-X» в пользовательских интерфейсах.
- Всегда используйте
LIMITвместе сORDER BY, если хотите, чтобы результаты были предсказуемыми.
В следующем модуле мы перейдем от простого извлечения строк к изучению агрегатных функций, которые позволяют вычислять итоговые суммы, средние значения и количество записей во всем наборе данных.