Документация верна; то есть вы можете запустить этот оператор:
select sum(wage) sum_of_all_wages
, count(1) count_of_all_records
from [dbo].[_abc]
having sum(wage) > 5
Причина, по которой ваш оператор не работает, связана с select *
, что означает выбор значения каждого столбца. Когда group by
нет, все записи агрегируются; то есть вы получаете только 1 запись в своем наборе результатов, которая должна представлять каждую запись. Таким образом, вы можете* включать только значения, полученные путем применения агрегатных функций к вашим столбцам; а не сами колонки. * конечно, вы также можете указать константы, поэтому select 'x' constant, count(1) cnt from myTable
будет работать.
Есть не так много вариантов использования, которые я могу придумать, где вы хотели бы использовать наличие без группы, но, безусловно, это можно сделать, как показано выше.
NB: если вам нужны все строки, в которых заработная плата больше 5, вместо этого вы должны использовать предложение where
:
select *
from [dbo].[_abc]
where wage > 5
Точно так же, если вы хотите, чтобы сумма всех заработных плат была больше 5, вы можете сделать это
select sum(wage) sum_of_wage_over_5
from [dbo].[_abc]
where wage > 5
Или, если вы хотите сравнить сумму заработной платы более 5 с заработной платой ниже:
select case when wage > 5 then 1 else 0 end wage_over_five
, sum(wage) sum_of_wage
from [dbo].[_abc]
group by case when wage > 5 then 1 else 0 end
См. выполняемые примеры здесь.
Обновление на основе комментариев:
Вам нужно having
для использования агрегатных функций?
Нет. Вы можете запустить select sum(wage) from [dbo].[_abc]
. Когда агрегатная функция используется без предложения group by
, это как если бы вы группировали по константе; то есть select sum(wage) from [dbo].[_abc] group by 1
.
Документация просто означает, что хотя обычно у вас будет оператор having
с оператором group by
, можно исключить group by
/ в таких случаях оператор having
, как и оператор select
, будет обрабатывать ваш запрос так, как если бы вы указали group by 1
.
В чем смысл?
Трудно придумать много хороших вариантов использования, поскольку вы возвращаете только одну строку, а оператор having
является фильтром для этого.
Одним из вариантов использования может быть то, что вы пишете код для мониторинга ваших лицензий на какое-то программное обеспечение; если у вас меньше пользователей, чем лицензий на пользователя, все хорошо / вы не хотите видеть результат, так как вам все равно. Если у вас есть больше пользователей, вы хотите знать об этом. Например.
declare @totalUserLicenses int = 100
select count(1) NumberOfActiveUsers
, @totalUserLicenses NumberOfLicenses
, count(1) - @totalUserLicenses NumberOfAdditionalLicensesToPurchase
from [dbo].[Users]
where enabled = 1
having count(1) > @totalUserLicenses
Разве выбор не имеет отношения к предложению наличия?
Да и нет. Наличие — это фильтр ваших агрегированных данных. Select указывает, какие столбцы/информацию нужно вернуть. Таким образом, вы должны спросить: «Как будет выглядеть результат?» т. е. Учитывая, что нам пришлось эффективно применять group by 1
, чтобы использовать оператор having
, как SQL должен интерпретировать select *
? Поскольку в вашей таблице есть только один столбец, это будет означать select wage
; но у нас есть 5 строк, поэтому 5 разных значений wage
и только 1 строка в результате, чтобы показать это.
Я думаю, вы могли бы сказать: «Я хочу вернуть все строки, если их сумма больше 5; в противном случае я не хочу возвращать строки». Если бы это было вашим требованием, это могло бы быть достигнуто различными способами; одним из которых будет:
select *
from [dbo].[_abc]
where exists
(
select 1
from [dbo].[_abc]
having sum(wage) > 5
)
Однако мы должны написать код, соответствующий требованиям, а не ожидать, что код поймет наши намерения.
Другой способ представить having
как оператор where
, применяемый к подзапросу. т.е. ваше исходное утверждение эффективно гласит:
select wage
from
(
select sum(wage) sum_of_wage
from [dbo].[_abc]
group by 1
) singleRowResult
where sum_of_wage > 5
Это не сработает, потому что wage
недоступно для внешнего запроса; возвращается только sum_of_wage
.
10.11.2018
how can I use having without using group by
как способ понять это. В стандартных случаях использования вы сначала должны иметь в виду цель, и ваш вопрос будетhow do I achieve this
. Как уже упоминалось, трудно придумать много примеров, где использованиеhaving
безgroup by
имело бы смысл; поэтому я бы посоветовал сделать мысленную пометку, что это вариант, и перейти к изучению чего-то еще; то в будущем, если вы столкнетесь с вариантом использования, надеюсь, вы вспомните это 10.11.2018