HAVING子句是如何工作的?

5
我们可以在SQL查询中使用HAVING子句来过滤行组。当我们使用GROUP BY子句时,它会直接按此方式工作。
但是,让我们看一下这个查询:
select 1 where 1!=1 having count(*)=0;

(或在Oracle中附加'from dual'。)

如果HAVING确实进行分组过滤,在WHERE之后我们没有任何行,因此我们没有任何分组,结果必须是“未选择任何行”。

但在PostgreSQL、MySQL和Oracle中,我们得到查询结果为“1”。

问题:HAVING的工作原理是什么?

用于测试的SQL Fiddle:http://www.sqlfiddle.com/#!15/d5407/51


检测一个表格是否有0行的愚蠢方法... - jarlh
WHERE 返回0行,因此我们有0组行。如果HAVING仅对行组进行过滤,为什么要开始并对空输入进行一些评估呢? - potapuff
2个回答

7
如果没有GROUP BY,聚合函数总是返回一行结果。在你的情况下,COUNT(*)返回0
这个列不在你的选择列表中,但是硬编码的文字1
select count(*) where 1!=1 ;
select 'bla' where 1!=1 having count(*)=0;

请查看这个网站

好的,如果HAVING没有GROUP BY,它总是会返回一行数据,这一行包含什么数据? - potapuff
@potapuff:如果没有匹配的行,“COUNT”返回零,“SUM”,“MIN”等则为NULL。 - dnoeth

3

HAVING没有GROUP BY子句也是有效的,并且作用于整个表。根据SQL标准92:

7.10

::= HAVING

Syntax Rules

1) 让HC成为 。让TE成为立即包含HC的 。

如果TE不立即包含GROUP BY(),则隐含了GROUP BY()。

以及:

::= GROUP BY

<grouping specification> ::=
<grouping column reference>
     | <rollup list>   
     | <cube list>   
     | <grouping sets list>   
     | <grand total>   
     | <concatenated grouping>

<grouping set> ::=
<ordinary grouping set>   
     | <rollup list>   
     | <cube list>   
     | <grand total>

<grand total> ::= <left paren> <right paren>

如您所见,GROUP BY () 被视为总计

在您的示例中,您有:

select 1 
where 1!=1 
having count(*)=0;

实际上是类似于:

select 1 
where 1!=1 
-- group by ()
having count(*)=0;

顺便提一句,大多数数据库(MySQL,PostgreSQL,Oracle)不支持 GROUP BY () :) - potapuff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接