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。