【发布时间】:2014-08-16 13:12:29
【问题描述】:
公平地说,WHERE 子句将在应用任何连接之前应用于行,而HAVING 子句将在应用所有连接和所有聚合函数后应用于最终结果集?
【问题讨论】:
-
从逻辑的角度来看,所有谓词(包括连接谓词)都是同时完成的——实际上,它们是按照优化器决定的任何顺序完成的。
公平地说,WHERE 子句将在应用任何连接之前应用于行,而HAVING 子句将在应用所有连接和所有聚合函数后应用于最终结果集?
【问题讨论】:
公平地说,在应用任何连接之前,将在行数据上应用 WHERE 子句
不,优化器可能会更改连接表的顺序。因此,从技术上讲,连接的表可能会在您在FROM 中指定的表之前。所以从技术上讲,来自WHERE 的条件可能会成为JOIN 条件的一部分。
在所有连接和所有聚合函数都已应用后,HAVING 子句将应用于最终结果集
没错
【讨论】:
WHERE 与 HAVING 仅对包含 GROUP BY 子句的 SQL 语句有意义。首先应用 WHERE 子句中的过滤谓词,然后是聚合,然后过滤 HAVING 子句中的谓词。
例子:
create table t(
a varchar2(10) not null
,b varchar2(10) not null
,n number not null
,primary key(a,b)
);
insert into t values('A', '1', 10);
insert into t values('A', '2', 20);
insert into t values('B', '1', -10);
insert into t values('B', '2', 10);
insert into t values('C', '1', 0);
insert into t values('C', '2', 10);
insert into t values('C', '3', 20);
在以下查询中,{C,1} 在聚合之前被删除。请参阅计数 (*)。
select a, sum(n), count(*)
from t
where n <> 0
group by a;
A SUM(N) COUNT(*)
== ====== =====
A 30 2
B 0 2
C 30 2
在此查询中,{B,1} 和 {B,2} 都被删除,因为它们的总和为 0。但请注意 {C,1} 被包括在内。
select a, sum(n), count(*)
from t
group by a
having sum(n) <> 0;
A SUM(N) COUNT(*)
== ====== =====
A 30 2
C 30 3
最后一点: WHERE 子句中的过滤谓词在before 连接操作之前执行。至少“逻辑上”。但是,我可以想象一些涉及对物化视图的查询重写的情况,例如带有索引的预连接表,而这在“幕后”工作有点不同。不过,结果是一样的。
【讨论】: