【问题标题】:How does the HAVING clause really work?HAVING 子句如何真正起作用?
【发布时间】:2015-10-30 07:40:20
【问题描述】:

我们可以在 SQL 查询中使用 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

【问题讨论】:

  • 检测表是否有 0 行的愚蠢方法...
  • WHERE 返回 0 行,所以我们有 0 组行。如果 HAVING 只做行组过滤,为什么要开始并为空输入做一些评估?

标签: mysql sql oracle postgresql having-clause


【解决方案1】:

如果没有GROUP BY,聚合总是返回一行,在您的情况下,COUNT(*) 返回0

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

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

fiddle

【讨论】:

  • 好的,如果没有 GROUP BY 的 HAVING 总是返回一行,这行包含什么数据?
  • @potapuff:如果没有匹配的行,COUNT 返回零,SUMMIN 等为 NULL。
【解决方案2】:

HAVING 没有GROUP BY cluase 是有效的并且对整个表进行操作。来自 SQL 标准 92:

7.10

::= 拥有

语法规则

1) 设 HC 为 .设 TE 是立即包含 HC 的那个。

如果 TE 不立即包含 a ,则 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;

【讨论】:

  • 顺便说一句,大多数数据库(MySQL、PostgreSQL、Oracle)不支持 GROUP BY () :)
猜你喜欢
  • 1970-01-01
  • 2017-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-23
  • 1970-01-01
  • 2013-01-07
  • 2017-06-22
相关资源
最近更新 更多