HAVING 子句如何真正起作用?

How does the HAVING clause really work?

我们可以在 SQL-query 中使用 HAVING 子句来过滤行组。当我们使用 GROUP BY 子句时,它直接以这种方式工作。

但是,让我们看看这个查询:

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

(或为 Oracle 添加 'from dual')。

如果HAVING真的进行分组过滤,WHERE之后我们没有任何行,所以我们没有任何分组,结果必须是'No row selected'。

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

问题:HAVING 到底是如何工作的?

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

没有 GROUP BY 子句的

HAVING 是有效的并且在整个 table 上运行。来自 SQL 标准 92:

7.10

::= HAVING

Syntax Rules

1) Let HC be the . Let TE be the that immediately contains HC.

If TE does not immediately contain a , then GROUP BY ( ) is implicit.

和:

::= 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 () 被视为 grand total

在你的例子中你有:

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

实际上是这样的:

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

如果没有 GROUP BY 聚合总是 returns 一行,在你的情况下 COUNT(*) returns 0.

此列不在您的 Select 列表中,而是硬编码文字 1

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

fiddle