Group by 和 Having Clause 使用多列
Group by and Having Clause that uses multiple columns
下面 Having
子句中的 AND
条件的行为就像它过滤行一样,即使满足其中一个条件时它应该是合乎逻辑的 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
的工作方式,我是不是遗漏了什么?我知道我可以解决这个问题,但我不明白为什么会这样。
这就是我得到的
这是我应该得到的
经过一番讨论,尝试使用这个
having not(SUM(Classes) =50 AND sum(Fees) =51)
OP 你写布尔值的时候要三思。
你好像不懂布尔逻辑。
没有 having 子句,这些就是你的结果
A 50 51
B 1 51
有
having ( SUM(Classes) !=50) AND (sum(Fees) !=51 )
您问:显示 类 不是 50 且费用不是 51.
的所有行
AND 很重要。
现在再看看没有子句的结果,问问自己为什么期望返回任何东西?
由于两行的费用都为 51,因此不会返回任何内容,因为您要求的行的费用不同于 51。
当您将 NOT(或 <> !=)与 AND 相加时,这是布尔逻辑中已知的思维陷阱。一般来说,你应该很少这样做。当你有多个 NOT 时,你应该用 OR 来累加它们,而不是 AND。
下面 Having
子句中的 AND
条件的行为就像它过滤行一样,即使满足其中一个条件时它应该是合乎逻辑的 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
的工作方式,我是不是遗漏了什么?我知道我可以解决这个问题,但我不明白为什么会这样。
这就是我得到的
这是我应该得到的
经过一番讨论,尝试使用这个
having not(SUM(Classes) =50 AND sum(Fees) =51)
OP 你写布尔值的时候要三思。
你好像不懂布尔逻辑。
没有 having 子句,这些就是你的结果
A 50 51
B 1 51
有
having ( SUM(Classes) !=50) AND (sum(Fees) !=51 )
您问:显示 类 不是 50 且费用不是 51.
的所有行AND 很重要。
现在再看看没有子句的结果,问问自己为什么期望返回任何东西?
由于两行的费用都为 51,因此不会返回任何内容,因为您要求的行的费用不同于 51。
当您将 NOT(或 <> !=)与 AND 相加时,这是布尔逻辑中已知的思维陷阱。一般来说,你应该很少这样做。当你有多个 NOT 时,你应该用 OR 来累加它们,而不是 AND。