#sql-server #tsql #having
#sql-сервер #tsql #наличие
Вопрос:
AND
Условие в приведенном ниже Having
предложении ведет себя так, как будто оно фильтрует строку, даже если выполняется одно из условий, когда оно должно быть логичным AND
поведением.
with cte as
( select 'A' as name , 10 as Classes , 11 as Fees union all
select 'A' as name , 10 as Classes , 10 as Fees union all
select 'A' as name , 10 as Classes , 10 as Fees union all
select 'A' as name , 10 as Classes , 10 as Fees union all
select 'A' as name , 10 as Classes , 10 as Fees union all
select 'B' as name , 0 as Classes , 10 as Fees union all
select 'B' as name , 0 as Classes , 10 as Fees union all
select 'B' as name , 1 as Classes , 10 as Fees union all
select 'B' as name , -10 as Classes , 10 as Fees union all
select 'B' as name , 10 as Classes , 11 as Fees
)
-- A has 50 rooms and 51 $ -- so it should not be returned
-- B has 1 room and 51 $ and should be fetched
-- why would the AND in the having clause behave like a row level filter on only the indivigual column
-- instead of the combination
-- The weird thing is the logic behaves as expected when using = but fails when using <>
select name , sum(Classes) , sUM(Fees)
from cte
group by name
having ( SUM(Classes) !=50) AND (sum(Fees) !=51 )
Вот странная часть, если вы замените != на =, как показано ниже, тогда все будет работать нормально
with cte as
( select 'A' as name , 10 as Classes , 11 as Fees union all
select 'A' as name , 10 as Classes , 10 as Fees union all
select 'A' as name , 10 as Classes , 10 as Fees union all
select 'A' as name , 10 as Classes , 10 as Fees union all
select 'A' as name , 10 as Classes , 10 as Fees union all
select 'B' as name , 0 as Classes , 10 as Fees union all
select 'B' as name , 0 as Classes , 10 as Fees union all
select 'B' as name , 1 as Classes , 10 as Fees union all
select 'B' as name , -10 as Classes , 10 as Fees union all
select 'B' as name , 10 as Classes , 11 as Fees
)
-- A has 50 rooms and 51 $ -- so it should not be returned
-- B has 1 room and 51 $ and should be fetched
-- why would the AND in the having clause behave like a row level filter on only the indivigual column
-- instead of the combination
-- The weird thing is the logic behaves as expected when using = but fails when using <>
select name , sum(Classes) , sUM(Fees)
from cte
group by name
having ( SUM(Classes) =1) AND (sum(Fees) =51 )
Я что-то упускаю, когда дело доходит до способа Group by
работы? Я знаю, что могу обойти проблему, но я не понимаю, почему она ведет себя таким образом.
Это то, что я получаю
Это то, что я должен получить
Комментарии:
1. предоставьте пример вывода из запросов и что следует ожидать, пожалуйста
2. пожалуйста, также укажите, что такое ваша БД и какая ошибка у вас возникает? это просто не возвращает нужные данные или у вас не был запущен запрос?
3. MS SQL 2019, ошибок нет, просто не получается ожидаемый результат, код выглядит правильно, поэтому мне просто нужно понять, почему он не работает так, как описано в документах
4. @user5785372 в любом случае
having ( SUM(Classes) !=50) AND (sum(Fees) !=51 )
, если последняя часть блокируетsum(Fees) = 51
arn’t it, вы должны использоватьor
notand
5. ИЛИ будет означать, что если либо классы sum, либо сборы Sum не совпадают, возвращается строка. Мне нужно получить строку, когда оба не совпадают
Ответ №1:
после некоторого обсуждения попробуйте использовать это
having not(SUM(Classes) =50 AND sum(Fees) =51)
и OP, вы должны дважды подумать, когда пишете логическое значение.
Ответ №2:
Похоже, вы не понимаете логическую логику.
без предложения having это ваши результаты
A 50 51
B 1 51
С помощью
having ( SUM(Classes) !=50) AND (sum(Fees) !=51 )
Вы спрашиваете: покажите мне все строки, для которых классы не равны 50, А сборы не 51.
Важно И .
Теперь посмотрите еще раз на результаты без предложения having и спросите себя, почему вы ожидаете, что что-то будет возвращено?
Поскольку обе строки имеют fee= 51, ничего не возвращается, потому что вы запрашиваете строки с fee, отличными от 51.
Это известная ловушка разума из логической логики, когда вы кумулируете NOT (или <> !=) с помощью ANDS . Вообще говоря, вам редко следует это делать. Если у вас есть несколько NOT, вы должны суммировать их с помощью OR , а не AND .