【问题标题】:Difference between ON and WHERE clauses in SQL table joinsSQL表连接中ON和WHERE子句的区别
【发布时间】:2012-10-19 09:44:48
【问题描述】:
select e.last_name, e.hire_date
from employees e join employees m
on (m.last_name = 'Davies')
and (e.hire_date > m.hire_date);

select e.last_name, e.hire_date
from employees e join employees m
on (m.last_name = 'Davies')
where (e.hire_date > m.hire_date);

select e.last_name, e.hire_date
from employees e join employees m
on (e.hire_date > m.hire_date)
where (m.last_name = 'Davies');

这三个语句的结果相同。除了where不能独占使用之外,不使用on,还有什么特别的理由在表连接中使用where

【问题讨论】:

  • 第一:你检查过查询计划吗?
  • 对于内部连接,我按照自己的想法布置代码。我把关于将这两种关系联系在一起的东西放在 ON 中。 (好吧,除了它们是包而不是集合之外的关系)并将过滤器放在 where 子句中。在您的示例中,表之间的关系是匹配 M 中的一行与 E 中满足e.hire_date > m.hiredate 的所有行。那将在我的加入。然后从 M 中选择特定行,`m.last_name = 'Davies' 将进入 where 子句。 (你有第三个查询。)

标签: sql oracle join


【解决方案1】:

主要区别在于您使用不同的联接时。

通常,如果您使用内连接,您应该会看到相同的结果,但是一旦您开始使用左连接,结果就会改变。

看看下面的例子

SQL Fiddle DEMO

And have a look at the following article (very explanatory)

编辑@ShannonSeverance

架构和测试数据

CREATE TABLE Table1 (
  ID INT,
  Val VARCHAR(20)
 );

INSERT INTO Table1 VALUES (1,'a');
INSERT INTO Table1 VALUES (2,'a');

CREATE TABLE Table2 (
  ID INT,
  Val VARCHAR(20)
 );

INSERT INTO Table2 VALUES (1,'a');

和测试

SELECT t1.ID,
t1.Val,
t2.ID ID2,
t2.Val Val2
FROM Table1 t1 INNER JOIN
Table2 t2 ON t1.ID = t2.ID AND t1.Val = t2.Val;

SELECT  t1.ID,
t1.Val,
t2.ID ID2,
t2.Val Val2
FROM Table1 t1,Table2 t2 
WHERE t1.ID = t2.ID
 AND t1.Val = t2.Val;

SELECT  t1.ID,
t1.Val,
t2.ID ID2,
t2.Val Val2
FROM Table1 t1 LEFT JOIN
Table2 t2 ON t1.ID = t2.ID  AND t1.Val = t2.Val;

SELECT  t1.ID,
t1.Val,
t2.ID ID2,
t2.Val Val2
FROM Table1 t1 LEFT JOIN
Table2 t2 ON t1.ID = t2.ID  
WHERE t1.Val = t2.Val;

【讨论】:

  • 很棒的文章。当然很好地总结了整个主题。
  • 我们能否获得一个嵌入在堆栈溢出答案中的差异示例?
  • @ShannonSeverance,我确实在 SQL Fiddle 链接中包含了一个示例。如果您愿意,我可以从那里复制并粘贴代码...
  • SQL Fiddle 链接是指向示例的指针,而不是示例本身。
【解决方案2】:

where 是一个过滤器,在使用连接选择行后应用。 join ... on 条件并不总是在语义上等同于 where 条件。因此,是的,在表连接中使用 where 有一个特殊的原因:当它做正确的事情时。


...相比之下,ON 条件在进行连接时执行。 ON 多表连接中较早的连接条件可以切断数百万个不必要的连接,因此如果语义正确,通常是首选
Bohemian

【讨论】:

  • ...相比之下,ON 条件在在进行连接时执行ON 多表连接中较早的连接条件可以切断数百万个不必要的连接,因此如果语义正确,通常是首选
  • 我明白了。 'on' 基本上选择行和 'where' 过滤它们。
  • @Jay 是的。您对on (m.last_name = 'Davies') 的使用相当不寻常,因为它确实属于where。通常on 用于标识一个表中的哪些行应该与另一个表中的其他行匹配(joined)。
  • 谢谢马特。我必须选择 asstander 的答案,因为它更具描述性并为我清除了。
  • @Bohemian ON 在进行连接时执行。 不可以。查询引擎必须提供“好像”所有连接及其各自的 ON 的结果子句在通过where 子句过滤之前进行了评估。但只要结果与隐含的执行顺序匹配,优化器就可以重新排序。
【解决方案3】:

使用on 通常用于查询多个表。进行该查询时,表之间必须具有关系,通常在特定字段中具有相同的值。

on 将连接相同的值,例如:

**table1**:

id_name   id_position   name
1         1             john
2         2             doe
3         2             tom
4         3             hawkins

**table2**
id_position   position
1             system analyst
2             programmer

SELECT t1.id_name, t1.name, t2.position
  FROM table1 t1 LEFT JOIN table2 t2
  ON t1.id_position = t2.id_position

-- RESULT:
id_name   name     position
1         john     system analyst
2         doe      programmer
3         tom      programmer
4         hawkins  NULL            -- NO MATCH IN table 2

我们可以看到on 将连接具有相同值id_position 的table1 和table2,所以它与您上面写的有点不同。

虽然where 可以在每个查询中使用,但并不取决于该查询中有多少表。一般来说,where 用于我们想要的有条件的东西。

【讨论】:

    【解决方案4】:

    区别在于引擎执行过滤的时间。 “where”表示对两个表的计算结果的过滤器。 “on”关键字指定如何执行连接。即使有时它们都产生相同的结果,它们在语义上也不等价。

    干杯

    【讨论】:

      【解决方案5】:

      ON 子句定义了表之间的关系。

      • ON 子句支持所有连接类型。

      WHERE 子句描述了您感兴趣的行。

      • WHERE 子句仅支持内连接,不支持外连接,如 LEFT JOINRIGHT JOIN

      【讨论】:

        猜你喜欢
        • 2012-01-08
        • 1970-01-01
        • 2012-05-13
        • 2014-05-17
        • 2015-04-22
        • 1970-01-01
        • 1970-01-01
        • 2021-04-22
        • 2011-02-25
        相关资源
        最近更新 更多