В чем разница между HAVING и WHERE в заявлении SQL SELECT?
Обновлено: Я отметил ответ Стивена как правильный, поскольку он содержал ключевой бит информации по ссылке:
When
GROUP BYis not used,HAVINGbehaves like aWHEREclause
В ситуации, в которой я видел WHERE, не было GROUP BY, и именно здесь началось мое замешательство. Конечно, пока вы этого не узнаете, вы не можете указать это в вопросе.
эта ссылка помогла мне понять это лучше, чем все комментарии ниже, думал, что кто-то может получить помощь от этого codeproject.com/Articles/25258/…


HAVING используется, когда вы используете агрегат, такой как GROUP BY.
SELECT edc_country, COUNT(*)
FROM Ed_Centers
GROUP BY edc_country
HAVING COUNT(*) > 1
ORDER BY edc_country;
Предложение HAVING было добавлено в SQL, поскольку ключевое слово WHERE нельзя было использовать с агрегатными функциями.
Ознакомьтесь с этим ссылка w3schools для получения дополнительной информации
Синтаксис:
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value
Такой запрос:
SELECT column_name, COUNT( column_name ) AS column_name_tally
FROM table_name
WHERE column_name < 3
GROUP
BY column_name
HAVING COUNT( column_name ) >= 3;
... может быть переписан с использованием производной таблицы (без HAVING) следующим образом:
SELECT column_name, column_name_tally
FROM (
SELECT column_name, COUNT(column_name) AS column_name_tally
FROM table_name
WHERE column_name < 3
GROUP
BY column_name
) pointless_range_variable_required_here
WHERE column_name_tally >= 3;
Вы немного упустили суть: HAVING был добавлен, потому что производные таблицы не были добавлены к языку и до тех пор, пока они не стали SQL, не был реляционно завершенным, и, как только они неизбежно стали, HAVING стал избыточным.
HAVING specifies a search condition for a group or an aggregate function used in SELECT statement.
Я использую HAVING для ограничения запроса на основе результатов агрегатной функции. НАПРИМЕР. выберите * в группе blahblahblah, ЧТО-ТО имея счет (ЧТО-ТО)> 0
От здесь.
the SQL standard requires that HAVING must reference only columns in the GROUP BY clause or columns used in aggregate functions
в отличие от предложения WHERE, которое применяется к строкам базы данных
Источник сообщает: «Использование позиций столбцов не рекомендуется, поскольку синтаксис был удален из стандарта SQL». К сожалению, это неправильно: из Стандарта никогда ничего не удаляется, и по иронии судьбы HAVING все еще существует спустя десятилетия после того, как он был «устарел» производными таблицами.
Немного педантично, но цитата неверна, например. рассмотрим SELECT 1 FROM T HAVING COUNT(*) >= 1; - не ссылается ни на столбцы в предложении GROUP BY (его нет), ни на столбцы в агрегатных функциях (запрос вообще не ссылается на столбцы).
HAVING: используется для проверки условий после, выполняется агрегация. ГДЕ: используется для проверки условий до, когда происходит агрегирование.
Этот код:
select City, CNT=Count(1)
From Address
Where State = 'MA'
Group By City
Дает вам таблицу всех городов в Массачусетсе и количество адресов в каждом городе.
Этот код:
select City, CNT=Count(1)
From Address
Where State = 'MA'
Group By City
Having Count(1)>5
Дает вам таблицу городов в Массачусетсе с более чем 5 адресами и количеством адресов в каждом городе.
Это должен быть принятый ответ. Различие между «иметь» и «где» сразу же проясняет это.
WHERE применяется как ограничение для набора, возвращаемого SQL; он использует встроенные операции набора и индексы SQL и, следовательно, является самым быстрым способом фильтрации наборов результатов. По возможности всегда используйте WHERE.
ИМЕТЬ необходимо для некоторых агрегатных фильтров. Он фильтрует запрос ПОСЛЕ того, как sql извлекает, собирает и отсортировывает результаты. Следовательно, он намного медленнее, чем WHERE, и его следует избегать, за исключением тех ситуаций, которые этого требуют.
SQL Server позволит вам обойтись без использования HAVING, даже если WHERE будет намного быстрее. Не делай этого.
Поддержка производных таблиц на языке SQL означает, что ваше утверждение «HAVING необходимо для некоторых агрегатных фильтров» неверно.
Неплохо подмечено. За три года, прошедшие с тех пор, как я написал этот ответ, я определенно перешел на использование производных таблиц, где раньше я бы использовал HAVING. Я не задумывался над вопросом, есть ли у HAVING еще какие-то разумные варианты использования. Я также не знаю, будет ли производная таблица универсально работать лучше, чем HAVING.
В агрегированном запросе (любой запрос, в котором используется агрегатная функция) Предикаты в предложении where оцениваются до создания агрегированного промежуточного набора результатов,
Предикаты в предложении Have применяются к совокупному набору результатов ПОСЛЕ того, как он был сгенерирован. Вот почему условия предиката для агрегированных значений должны быть помещены в предложение Have, а не в предложение Where, и почему вы можете использовать псевдонимы, определенные в предложении Select в предложении Have, но не в предложении Where.
У меня возникла проблема, и я обнаружил еще одно различие между WHERE и HAVING. Это не действует так же на индексированные столбцы.
WHERE my_indexed_row = 123 покажет строки и автоматически выполнит «ORDER ASC» для других проиндексированных строк.
HAVING my_indexed_row = 123 показывает все, от самой старой «вставленной» строки до самой новой, без упорядочивания.
Откуда вы знаете, что это определенная разница между двумя, а не случайность реализации конкретного SQL-сервера, который вы использовали?
Я только что тестировал на MariaDB. Думаю, именно тот SQL-сервер, который я использовал 8 лет назад, дал разные результаты.
Разница номер один для меня: если бы HAVING был удален из языка SQL, жизнь продолжалась бы более или менее, как раньше. Конечно, запросы меньшинства должны быть переписаны с использованием производной таблицы, CTE и т. д., Но в результате их, возможно, будет легче понять и поддерживать. Возможно, потребуется переписать код оптимизатора поставщиков, чтобы учесть это, что снова является возможностью для улучшений в отрасли.
Теперь рассмотрим удаление WHERE из языка. На этот раз большинство существующих запросов нужно будет переписать без очевидной альтернативной конструкции. Кодерам придется проявить творческий подход, например, внутреннее соединение с таблицей, которая, как известно, содержит ровно одну строку (например, DUAL в Oracle), с использованием предложения ON для имитации предыдущего предложения WHERE. Такие конструкции будут надуманными; было бы очевидно, что в языке чего-то не хватает, и в результате ситуация ухудшится.
TL; DR мы можем потерять HAVING завтра, и все будет не хуже, возможно, лучше, но этого нельзя сказать о WHERE.
Из ответов здесь кажется, что многие люди не понимают, что предложение HAVING может использоваться без предложения GROUP BY. В этом случае предложение HAVING применяется ко всему табличному выражению и требует, чтобы в предложении SELECT появлялись только константы. Обычно пункт HAVING включает агрегаты.
Это более полезно, чем кажется. Например, рассмотрите этот запрос, чтобы проверить, является ли столбец name уникальным для всех значений в T:
SELECT 1 AS result
FROM T
HAVING COUNT( DISTINCT name ) = COUNT( name );
Есть только два возможных результата: если предложение HAVING истинно, то результатом будет одна строка, содержащая значение 1, в противном случае результатом будет пустой набор.
Будет ли это эквивалентно «ВЫБРАТЬ СЧЕТЧИК (РАЗЛИЧНОЕ имя) = СЧЕТЧИК (имя) ОТ T»?
@MSpreij Не знаю, работает ли это для вас, но он не работает на SQL Server 2005, но первый работает
Во время работы над проектом это тоже был мой вопрос. Как указано выше, ИМЕЮЩИЕ проверяет условие для уже найденного результата запроса. Но ГДЕ предназначен для проверки условия во время выполнения запроса.
Приведу пример, чтобы проиллюстрировать это. Предположим, у вас есть такая таблица базы данных.
usertable{ int userid, date datefield, int dailyincome }
Допустим, в таблице есть следующие строки:
1, 2011-05-20, 100
1, 2011-05-21, 50
1, 2011-05-30, 10
2, 2011-05-30, 10
2, 2011-05-20, 20
Теперь мы хотим получить userid и sum(dailyincome), у которых sum(dailyincome)>100
Если мы напишем:
SELECT userid, sum(dailyincome) FROM usertable WHERE sum(dailyincome)>100 GROUP BY userid
Это будет ошибкой. Правильный запрос будет:
SELECT userid, sum(dailyincome) FROM usertable GROUP BY userid HAVING sum(dailyincome)>100
Разница между ними заключается во взаимосвязи с предложением GROUP BY:
ГДЕ предшествует GROUP BY; SQL оценивает предложение WHERE перед группировкой записей.
HAVING следует после GROUP BY; SQL оценивает HAVING после того, как группирует записи.
использованная литература
Синтаксис оператора SQLite SELECT / железнодорожная диаграмма
Синтаксис оператора Informix SELECT / железнодорожная диаграмма
Поскольку GROUP BY и HAVING являются необязательными, на диаграмме показаны оба случая, просто следуйте стрелкам.
Пример запроса из моего ответа на этот вопрос: SELECT 1 AS result FROM T HAVING... - на вашей диаграмме я не могу добраться до HAVING, не пройдя через GROUP BY, но в моем совершенно правильном и полезном запросе нет GROUP BY. Незначительный момент: у вас нет возможности включать буквальные значения в предложение SELECT.
@onedaywhen Поскольку тебе известно о неявном GROUP BY, почему вы не упомянули об этом? Вы знаете, ожидаете ли вы это поведение или нет?
Мне кажется, вы цитируете меня вне контекста. Вопрос касался очевидного отклонения mySQL от Стандарта, все, кроме последнего абзаца моего ответа, описывают стандартное поведение, а последний намекает на «неявное предложение GROUP BY упомянутые в других ответах». Вы говорите, что ваша диаграмма предназначена для описания (всего) неявного поведения? Разве не было бы более полезным придерживаться только того кода, который вам нужно написать, чтобы получить желаемое поведение?
... Я не знаю, о каком поведении вы говорите во второй ссылке. Желаемый результат состоит в том, чтобы вы исправили диаграмму, чтобы показать действительный (явный) путь, о котором я упоминал. Подумайте об этом: диаграмма охватывает весь запрос, но вопрос интересует только часть WHERE->HAVING, поэтому я думаю, что заслуживает пристального внимания к деталям. Если вы считаете, что мой ответ неверен, отредактируйте его или опубликуйте предлагаемое исправление в комментариях.
@onedaywhen Во второй ссылке упоминается HAVING condition applied to rows rather than groups. Это нестандартно или стандартно? Всегда ли, никогда или иногда неявная GROUP BY? Является ли это поведение на 100% совместимым со стандартами, устаревшим, антипаттерном, зависимым от реализации или перспективным в будущем?
«Условие HAVING применяется к строкам, а не к группам» для меня звучит неправильно. ИМО, поведение лучше изложить в том же ответе: «Предложение имеющее исключает строки из окончательных результатов, которые не соответствуют его условиям поиска», просто так, 100% стандартное соответствие. Если нет GROUP BY, значит, неявная группировка отсутствует. Но я все еще немного смущен тем, как это связано с вашей диаграммой, отсутствует действительный путь.
Быстрое доказательство: CREATE TABLE T (c CHAR(1)); INSERT INTO T VALUES ('a'),('a'); SELECT 'true' FROM T HAVING COUNT (c) = 2; должен быть результатом с одной строкой и одним столбцом, показывающим true, потому что условие поиска не удаляет строки, то есть не применяет неявную группу по (если бы он был сгруппирован, то COUNT(c) был бы 1, условие поиска завершилось бы ошибкой, т.е. результат нулевой строки ).
Вводящая в заблуждение синтаксическая диаграмма не сообщает спрашивающему о семантический (а не синтаксической) разнице между двумя.
Предложение WHERE используется для сравнения значений в базовой таблице, тогда как предложение HAVING может использоваться для фильтрации результатов агрегатных функций в наборе результатов запроса. Нажмите здесь!
Предложение WHERE не работает для агрегатных функций
означает: вы не должны так использовать
бонус: название таблицы
SELECT name
FROM bonus
GROUP BY name
WHERE sum(salary) > 200
ЗДЕСЬ Вместо предложения WHERE вы должны использовать HAVING ..
без использования предложения GROUP BY предложение HAVING работает как предложение WHERE
SELECT name
FROM bonus
GROUP BY name
HAVING sum(salary) > 200
Когда GROUP BY не используется, пункты WHERE и HAVING по существу эквивалентны.
Однако при использовании GROUP BY:
WHERE используется для фильтрации записей из результата. В
фильтрация происходит до того, как будут произведены какие-либо группировки.HAVING используется для фильтрации значений из группы (т.е.
условия проверки после выполнения объединения в группы).Ресурс от Здесь
имеющий и где по существу не эквивалентны. он выдаст ошибку при выполнении. недопустимо в предложении HAVING, поскольку оно не содержится ни в агрегатной функции, ни в предложении GROUP BY.
Один из способов подумать об этом состоит в том, что предложение Have является дополнительным фильтром к предложению where.
Предложение ГДЕ используется для фильтрации записей из результата. Фильтр выполняется до того, как будут сделаны какие-либо группировки. Предложение ИМЕЮЩИЕ используется для фильтрации значений из группы
Разница ч / б WHERE и HAVING пункт:
Основное различие между предложением WHERE и HAVING заключается в том, что WHERE используется для операций со строками, а HAVING используется для операций со столбцами.
Зачем нужна оговорка HAVING?
Как мы знаем, агрегатные функции могут выполняться только для столбцов, поэтому мы не можем использовать агрегатные функции в предложении WHERE. Поэтому мы используем агрегатные функции в предложении HAVING.
Когда GROUP BY не используется, предложения WHERE и HAVING по существу эквивалентны.
Однако при использовании GROUP BY:
Предложение Where используется для фильтрации строк по всей базе данных. Но предложение Have используется для фильтрации строк из определенной группы базы данных. Предложение Наличие также может помочь в совокупной функции, такой как мин / макс / среднее
подробнее .. в чем разница между WHERE и HAVINGв чем разница между WHERE и HAVING
Я здесь, если тебе нужна другая помощь
Почему тебе не понравился пост ??
Цитируемая вами строка вовсе не является ключевым моментом. Ключевой бит, как указал wcm, заключается в том, что
HAVINGявляется фильтром постагрегации, тогда какWHEREявляется фильтром до агрегирования.