WHERE и HAVING вместе
В запросе могут быть и WHERE, и HAVING, и у каждого своя задача. WHERE фильтрует строки до группировки: строки, не удовлетворяющие его условию, не попадают ни в одну группу. HAVING фильтрует группы после того, как они созданы и посчитаны.
В каких жанрах не меньше 3 уже вышедших игр? Вышла ли игра — вопрос об одной строке, поэтому он идёт в WHERE. «Не меньше 3» относится к целой группе, поэтому идёт в HAVING:
SELECT genre, COUNT(*) AS released_games
FROM games
WHERE released IS NOT NULL
GROUP BY genre
HAVING COUNT(*) >= 3
ORDER BY genre;| genre | released_games |
|---|---|
| Action | 3 |
| Strategy | 3 |
В предыдущем упражнении в жанре Adventure тоже было 3 игры. Но одна из них, Mystery Manor, ещё не вышла, и WHERE отбрасывает её до подсчёта. Тогда в Adventure остаётся только 2 игры, и HAVING убирает этот жанр. В Action было 4 игры, а теперь учитываются только 3 вышедшие.
Как понять, где место условию? Спросите себя, можно ли решить его, посмотрев на одну строку. «Уже вышла», «оплачен», «из города London»: достаточно одной строки, значит, WHERE. «Не меньше 3 игр», «больше $60 в сумме», «в среднем 4 звезды»: нужна вся группа, значит, HAVING. Условие по столбцу, по которому вы группируете, например genre = 'Action', сработало бы в обоих местах, но поставьте его в WHERE: тогда база данных не будет группировать строки, которые всё равно отбросит.
Типичная ошибка: условие о строках в HAVING. Другие базы данных сообщают об ошибке, потому что столбца нет в GROUP BY. SQLite — нет: он проверяет дату выхода одной игры из каждой группы и по ней оставляет или отбрасывает всю группу. Здесь он оставляет все жанры со всеми их играми:
SELECT genre, COUNT(*) AS released_games
FROM games
GROUP BY genre
HAVING released IS NOT NULL
ORDER BY genre;| genre | released_games |
|---|---|
| Action | 4 |
| Adventure | 3 |
| … | … |
Ошибки нет, зато результат неверный: в Action снова 4 игры, включая Robot Rebellion, которая ещё не вышла.
Задание
- 1
Посчитайте только оплаченные заказы каждого клиента (
statusравен'paid') и покажите клиентов, у которых их не меньше 3:customer_idи количество в столбцеpaid_orders, отсортировав поcustomer_id:customer_id paid_orders 1 4 2 3 3 4 4 3 - 2
Ниже посчитайте клиентов, зарегистрировавшихся в 2024 году или позже, в каждом городе и покажите только города, где их не меньше 2:
cityи количество в столбцеnew_customers, отсортировав по городу:city new_customers Bristol 3 London 2 Manchester 2