27

SQL1:

select t1.f1,t2.f2 
from t1 
   left join t2 on t1.f1 = t2.f2 and t1.f2=1 and t1.f3=0 

SQL2:

select t1.f1,t2.f2 
from t1 
  left join t2 on t1.f1 = t2.f2 
where t1.f2=1 and t1.f3=0

区别在于whereon子句,它返回相同的结果吗?有什么区别?DBMS 是否以相同的方式运行它们?谢谢。

4

6 回答 6

26

where子句适用于整个结果集;onclause仅适用于有问题的连接。

在提供的示例中,所有附加条件都与连接内侧的字段相关 - 因此在此示例中,两个查询实际上是相同的。

但是,如果您在联接外侧的表中包含值的条件,则会产生显着差异。

您可以从此链接获得更多信息:http: //ask.sqlservercentral.com/questions/80067/sql-data-filter-condition-in-join-vs-where-clause

例如:

select t1.f1,t2.f2 from t1 left join t2 on t1.f1 = t2.f2 and t2.f4=1

select t1.f1,t2.f2 from t1 left join t2 on t1.f1 = t2.f2 where t2.f4=1

- 做不同的事情 - 前者将左连接到 f4 为 1 的 t2 记录,而后者已有效地转回到 t2 的内部连接。

于 2011-11-29T13:02:49.377 回答
8

第一个查询比第二个查询快,因为连接条件比第二个查询更具体:返回将使用 where 子句过滤的记录是没有意义的(最好根本不返回它们 - query1 )

无论如何,它确实取决于查询优化器。

看看下面:

JOIN 比 WHERE 快吗?

于 2011-11-29T13:02:37.043 回答
5

在考虑 SQL 语法时,了解SQL 操作的逻辑顺序很重要。是子句中JOIN的运算符(并且ON属于相关的JOIN) 。FROMFROM子句是第一个在逻辑上执行的操作(优化器仍然可以选择重新排序)。

在您的示例中,并没有真正的区别,但很容易构建一个,正如我在这篇博客文章中展示的关于和之间的区别ON(博客文章WHEREOUTER JOIN的示例使用Sakila 数据库):

第一次查询

SELECT a.actor_id, a.first_name, a.last_name, count(fa.film_id)
FROM actor a
LEFT JOIN film_actor fa ON a.actor_id = fa.actor_id
WHERE fa.film_id < 10
GROUP BY a.actor_id, a.first_name, a.last_name
ORDER BY count(fa.film_id) ASC;

产量:

ACTOR_ID  FIRST_NAME  LAST_NAME  COUNT
--------------------------------------
194       MERYL       ALLEN      1
198       MARY        KEITEL     1
30        SANDRA      PECK       1
85        MINNIE      ZELLWEGER  1
123       JULIANNE    DENCH      1

WHERE因为我们在子句中过滤了外连接表,所以LEFT JOIN实际上变成了INNER JOIN. 为什么?因为如果我们有一个没有在电影中扮演的演员,那么那个演员的唯一行就会有fa.film_id IS NULLfa.film_id < 10谓词就会因此而让出NULL。这样的参与者被排除在结果之外,就像INNER JOIN.

第二次查询

SELECT a.actor_id, a.first_name, a.last_name, count(fa.film_id)
FROM actor a
LEFT JOIN film_actor fa ON a.actor_id = fa.actor_id
  AND fa.film_id < 10
GROUP BY a.actor_id, a.first_name, a.last_name
ORDER BY count(fa.film_id) ASC;

产量:

ACTOR_ID  FIRST_NAME  LAST_NAME     COUNT
-----------------------------------------
3         ED          CHASE         0
4         JENNIFER    DAVIS         0
5         JOHNNY      LOLLOBRIGIDA  0
6         BETTE       NICHOLSON     0
...
1         PENELOPE    GUINESS       1
200       THORA       TEMPLE        1
2         NICK        WAHLBERG      1
198       MARY        KEITEL        1

现在,结果中包含没有电影的演员,因为fa.film_id < 10谓词是LEFT JOINON谓词的一部分

结论

始终将谓词放在逻辑上最有意义的地方。

  • 它们是您JOIN运营的一部分吗?将它们放入ON
  • 它们是否过滤了您的整个JOIN产品?将它们放入WHERE
于 2020-03-05T16:34:44.483 回答
3

这两个查询相同。

Mark Ba​​nnister 正确地指出该where子句适用于整个结果集,但 onclause适用于联接。

在您的情况下,对于 SQL 1 LEFT JOIN 条件,过滤器连接在右侧,但左侧总是在任何 WHERE 过滤之前返回。由于没有 WHERE 条件,所有 t1 总是返回。

在 SQL 2 中,LEFT JOIN 条件过滤了一些显示在右侧的结果,但又返回了所有 t1。但是这次 WHERE 条件可能会过滤掉一些 t1 的记录。

INSERT INTO `t1` (`f1`,`f2`,`f3`) VALUES (1,1,1); INSERT INTO `t2` (`f3`) VALUES (1);

由于它们指向不同的逻辑,因此必须基于该逻辑编写查询,这为我们提供了强大的功能和灵活性。

然而,INNER JOIN 返回相同的结果,所以是的,请检查优化器。

于 2018-04-19T07:01:38.383 回答
2

关系代数允许 WHERE 子句和 INNER JOIN 中的谓词可互换,因此即使带有 WHERE 子句的 INNER JOIN 查询也可以让优化器重新排列谓词,以便它们可能在 JOIN 过程中已经被排除。

我建议您以最易读的方式编写查询。

有时这包括使 INNER JOIN 相对“不完整”,并将一些条件放在 WHERE 中,以使过滤条件列表更易于维护。

您可以从此链接获得更多信息:http: //ask.sqlservercentral.com/questions/80067/sql-data-filter-condition-in-join-vs-where-clause

例如,而不是:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
    AND c.State = 'NY'
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
    AND a.Status = 1

写:

SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
    ON ca.CustomerID = c.CustomerID
INNER JOIN Accounts a
    ON ca.AccountID = a.AccountID
WHERE c.State = 'NY'
    AND a.Status = 1

但这当然取决于。

于 2011-11-29T13:29:08.317 回答
1

1)

SQL1: select t1.f1,t2.f2 from t1 left join t2 on t1.f1 = t2.f2 **and** t1.f2=1 and t1.f3=0 

在此,解析器将使用这 3 个条件检查 t1 的每一行和 t2 的每一行。获得更快的结果。

2)SQL2: select t1.f1,t2.f2 from t1 left join t2 on t1.f1 = t2.f2 **where** t1.f2=1 and t1.f3=0

在这种情况下,join 仅采用第一个条件,然后使用这两个条件过滤从 join 获得的结果。并且将比第一次查询花费更多时间。

您可以从此链接获得更多信息:http: //ask.sqlservercentral.com/questions/80067/sql-data-filter-condition-in-join-vs-where-clause

于 2011-11-29T13:03:38.190 回答