Чем отличается HAVING от WHERE?
Почему данную выборку нельзя переписать с использованием WHERE?
SELECT StudentId FROM EXAM_RESULT GROUP BY StudentID HAVING MIN(Mark) = 5
- Вопрос задан более трёх лет назад
- 20374 просмотра
Комментировать
Решения вопроса 3
Сергей Горностаев @sergey-gornostaev Куратор тега SQL
Седой и строгий
Основное отличие WHERE от HAVING заключается в том, что WHERE сначала выбирает строки, а затем группирует их и вычисляет агрегатные функции (таким образом, она отбирает строки для вычисления агрегатов), тогда как HAVING отбирает строки групп после группировки и вычисления агрегатных функций. Как следствие, предложение WHERE не должно содержать агрегатных функций; не имеет смысла использовать агрегатные функции для определения строк для вычисления агрегатных функций. Предложение HAVING, напротив, всегда содержит агрегатные функции. (Строго говоря, вы можете написать предложение HAVING, не используя агрегаты, но это редко бывает полезно. То же самое условие может работать более эффективно на стадии WHERE.)
Ответ написан более трёх лет назад
Комментировать
Нравится 4 Комментировать
maksfedorov.ru
Чтобы понять, что у студента Mark=5 — минимальный, нужно сгруппировать значения, вдруг не минимальный (помимо проверки — есть он или нет).
То есть чтобы полностью ваше условие проверить, нужно точно группировать, WHERE просто проверит — есть такое значение или нет и выведет студентов, у которых есть
WHERE же используется движком на момент выборки, физически не возможно узнать минимальное значение
HAVING же уже работает с агрегирующими функциями, то есть мы сгруппировали, посчитали нужной функцией (минимальное значение в вашем случае), а HAVING уже выдал с условием этого подсчета
Ответ написан более трёх лет назад
Комментировать
Нравится 1 Комментировать
Готовые решения — не подаю, но.
Можно и переписать. но в виде извращенного каскада вложенных селектов:
— внутренний будет вываливать сгруппированные StudentId и MIN(Mark)
— внешний будет селектить StudentId с условие where
Ответ написан более трёх лет назад
Комментировать
Нравится 1 Комментировать
Ответы на вопрос 0
Ваш ответ на вопрос
Войдите, чтобы написать ответ

- SQL
- +1 ещё
Массив структур в Hive. Как проверить вхождение в массив структуры по маске?
- 1 подписчик
- вчера
- 72 просмотра
Чем отличается WHERE от HAVING?

Обсудим такой популярный вопрос на собеседовании, как «Чем отличается WHERE от HAVING»?
SELECT username, COUNT(*) FROM table WHERE username = ‘Anna’ GROUP BY username HAVING COUNT(*)>1Ой, скажет кто-то, зачем же спрашивать такие банальности? Как ни странно, довольно много разработчиков даже с сертификатами по SQL quering не понимают, что происходит в HAVING.
Давайте разберёмся. В сущности, HAVING очень похож на WHERE - это тоже фильтр. Вы можете написать в HAVING name = ‘Anna’, как и в WHERE, и ошибки не будет.
В чём же ключевое различие?
Во-первых, в HAVING и только в нём можно писать условия по агрегатным функциям (SUM, COUNT, MAX, MIN и т. д.). То есть если вы хотите сделать что-то вроде COUNT() > 10, то это возможно сделать только в HAVING*.
"Почему бы не оставить только HAVING?" - спросите вы. Всё кроется в том, как SQL Server выполняет запрос, в каком порядке происходит его разбор и работа с данными. WHERE выполняется до формирования групп GROUP BY. Это нужно для того, чтобы можно было оперировать как можно меньшим количеством данных и сэкономить ресурсы сервера и время пользователя.
Следующим этапом формируются группы, которые указаны в GROUP BY. После того как сформированы группы, можно накладывать условия на результаты агрегатных функций. И тут как раз наступает очередь HAVING: выполняются условия, которые вы задали.
Главное отличие HAVING от WHERE в том, что в HAVING можно наложить условия на результаты группировки, потому что порядок исполнения запроса устроен таким образом, что на этапе, когда выполняется WHERE, ещё нет групп, а HAVING выполняется уже после формирования групп.
Остались вопросы? Пишите их в комментариях!
Секция HAVING
Позволяет фильтровать результаты агрегации, полученные с помощью GROUP BY. Разница с WHERE в том, что WHERE выполняется перед агрегацией, в то время как HAVING выполняется после него.
Из секции HAVING можно ссылаться на результаты агреации из секции SELECT по их алиасу. Также секция HAVING может фильтровать по результатам дополнительных агрегатов, которые не возвращаются в результатах запроса.
Ограничения
HAVING нельзя использовать, если агрегация не выполняется. Вместо этого можно использовать WHERE .
Фильтрация c помощью оператора HAVING — Основы SQL
Иногда встречаются задачи, в которых требуется отфильтровать записи после группировки.
Для примера представим, что нам нужно вывести суммарное время, проведенное на платформе каждым пользователем:
SELECT user_id, SUM(spent_minutes) FROM course_reviews GROUP BY user_id ORDER BY user_id;Мы видим, что кто-то из пользователей провел много времени, а кто-то — совсем мало. Мы можем выбрать пользователей, которые провели на платформе меньше 30 минут, а затем связаться с ними и узнать, что именно им не понравилось.
Подобные условия невозможно задать с помощью WHERE , потому что они применяются к выборке до момента группировки. У нас немного другой случай — мы хотим задать условие на результат агрегатной функции после проведения группировки.
В этой задаче понадобится дополнение к GROUP BY , которое называется HAVING . Именно его мы изучим в этом уроке.
Ключевое слово HAVING
С помощью ключевого слова HAVING мы можем задать условия на строки выборки после группировки данных.
Попробуем найти пользователей, которые потратили менее 30 минут в онлайн-школе. Для этого напишем такой запрос:
SELECT user_id, SUM(spent_minutes) FROM course_reviews GROUP BY user_id HAVING SUM(spent_minutes) 30 ORDER BY user_id;Таких пользователей оказалось 6 человек.
Чем HAVING отличается от WHERE
Давайте дополним наш запрос — укажем, что искать пользователей мы будем только среди первых 40 человек. Для этого добавим условие user_id < = 40 :
SELECT user_id, SUM(spent_minutes) FROM course_reviews WHERE user_id 40 GROUP BY user_id HAVING SUM(spent_minutes) 30 ORDER BY user_id;Обратим внимание на синтаксис запроса. Условия в HAVING проверяются после группировки, поэтому они задаются после предложения GROUP BY . В этом и состоит отличие от условий WHERE , которые применяются к строкам исходной таблицы до группировки.
Таким образом, сначала мы убрали из исходной таблицы всех пользователей с user_id > 40 , затем провели группировку и посчитали суммарное время, а после этого отсеяли тех, кто пользовался платформой дольше 30 минут.
В этой ситуации мы могли бы добавить условие на user_id и в HAVING и получили бы тот же результат:
SELECT user_id, SUM(spent_minutes) FROM course_reviews GROUP BY user_id HAVING SUM(spent_minutes) 30 AND user_id 40 ORDER BY user_id;

