【问题标题】:Is WHERE clause applied before JOINWHERE 子句是否在 JOIN 之前应用
【发布时间】:2014-08-16 13:12:29
【问题描述】:

公平地说,WHERE 子句将在应用任何连接之前应用于行,而HAVING 子句将在应用所有连接和所有聚合函数后应用于最终结果集?

【问题讨论】:

  • 从逻辑的角度来看,所有谓词(包括连接谓词)都是同时完成的——实际上,它们是按照优化器决定的任何顺序完成的。

标签: oracle join where having


【解决方案1】:

公平地说,在应用任何连接之前,将在行数据上应用 WHERE 子句

不,优化器可能会更改连接表的顺序。因此,从技术上讲,连接的表可能会在您在FROM 中指定的表之前。所以从技术上讲,来自WHERE 的条件可能会成为JOIN 条件的一部分。

在所有连接和所有聚合函数都已应用后,HAVING 子句将应用于最终结果集

没错

【讨论】:

    【解决方案2】:

    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 连接操作之前执行。至少“逻辑上”。但是,我可以想象一些涉及对物化视图的查询重写的情况,例如带有索引的预连接表,而这在“幕后”工作有点不同。不过,结果是一样的。

    【讨论】:

      猜你喜欢
      • 2012-04-25
      • 2013-05-14
      • 2018-09-05
      • 1970-01-01
      • 2011-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多