简体   繁体   English

在SQL / MySQL中,join语句中的“ ON”和“ WHERE”有什么区别?

[英]In SQL / MySQL, what is the difference between “ON” and “WHERE” in a join statement?

The following statements give the same result (one is using on , and the other using where ): 以下语句给出相同的结果(一个使用on ,另一个使用where ):

mysql> select * from gifts INNER JOIN sentGifts ON gifts.giftID = sentGifts.giftID;
mysql> select * from gifts INNER JOIN sentGifts WHERE gifts.giftID = sentGifts.giftID;

I can only see in a case of a Left Outer Join finding the "unmatched" cases: 我只能在左外连接的情况下找到“无与伦比”的情况:
(to find out the gifts that were never sent by anybody) (找出从未有人送过的礼物)

mysql> select name from gifts LEFT OUTER JOIN sentgifts 
           ON gifts.giftID = sentgifts.giftID 
           WHERE sentgifts.giftID IS NULL;

In this case, it is first using on , and then where . 在这种情况下,它首先使用on ,然后使用where Does the on first do the matching, and then where does the "secondary" filtering? on先进行匹配,然后where “次要”过滤中进行过滤吗? Or is there a more general rule of using on versus where ? 还是onwhere上使用更一般的规则? Thanks. 谢谢。

The ON clause defines the relationship between the tables. ON子句定义表之间的关系。

The WHERE clause describes which rows you are interested in. WHERE子句描述您感兴趣的行。

Many times you can swap them and still get the same result, however this is not always the case with a left outer join. 很多时候,您可以交换它们并仍然获得相同的结果,但是,左外部联接并不总是这样。

  • If the ON clause fails you still get a row with columns from the left table but with nulls in the columns from the right table. 如果ON子句失败,您仍然会获得带有左表列的行,而右表列的行为空。
  • If the WHERE clause fails you won't get that row at all. 如果WHERE子句失败,那么您将根本不会获得该行。

WHERE is a part of the SELECT query as a whole, ON is a part of each individual join. WHERE是整个SELECT查询的一部分, ON是每个单独联接的一部分。

ON can only refer to the fields of previously used tables. ON只能引用以前使用的表的字段。

When there is no actual match against a record in the left table, LEFT JOIN returns one record from the right table with all fields set to NULLS . 当与左表中的记录没有实际匹配时, LEFT JOIN从右表中返回一条记录,且所有字段都设置为NULLS WHERE clause then evaluates and filter this. 然后, WHERE子句对此求值并进行过滤。

In your query, only the records from gifts without match in 'sentgifts' are returned. 在您的查询中,仅返回“ sentgifts”中不匹配的gifts的记录。

Here's the example 这是例子

gifts

1   Teddy bear
2   Flowers

sentgifts

1   Alice
1   Bob

---
SELECT  *
FROM    gifts g
LEFT JOIN
        sentgifts sg
ON      g.giftID = sg.giftID

---

1  Teddy bear   1     Alice
1  Teddy bear   1     Bob
2  Flowers      NULL  NULL    -- no match in sentgifts

---
SELECT  *
FROM    gifts g
LEFT JOIN
        sentgifts sg
ON      g.giftID = sg.giftID
WHERE   sg.giftID IS NULL

---

2  Flowers      NULL  NULL    -- no match in sentgifts

As you can see, no actual match can leave a NULL in sentgifts.id , so only the gifts that had not ever been sent are returned. 如您所见,没有任何实际匹配项可以在sentgifts.id保留NULL ,因此仅返回从未发送过的礼物。

When using INNER JOIN , ON and WHERE will have the same result. 使用INNER JOINONWHERE将具有相同的结果。 So, 所以,

select *
from Table1 t1
inner join Table2 t2 on t1.id = t2.id
where t1.Name = 'John'

will have the exact same output as 将具有与输出完全相同的输出

select *
from Table1 t1
inner join Table2 t2 on t1.id = t2.id
    and t1.Name = 'John'

As you have noted, this is not the case when using OUTER JOIN . 您已经注意到,使用OUTER JOIN时不是这种情况。 What query plan gets built is dependent on the database platform as well as query specifics, and is subject to change, so making decisions on that basis alone is not going to give a guaranteed query plan. 构建哪种查询计划取决于数据库平台以及查询的具体情况,并且可能会发生变化,因此仅在此基础上做出决定并不能提供有保证的查询计划。

As a rule of thumb, you should use columns that join your tables in ON clauses and columns that are used for filtering in WHERE clauses. 根据经验,应使用在ON子句中连接表的列和在WHERE子句中用于过滤的列。 This provides the best readability. 这提供了最佳的可读性。

Though the results are same, the 'ON' make the join first and then retrieve the data of the joined set. 尽管结果相同,但“ ON”将首先进行联接,然后检索联接集的数据。 The retrieval is faster and load is less. 检索速度更快,负载也更少。 But using 'WHERE' cause the two result sets to be fetched first and then apply the condition. 但是使用“ WHERE”会导致首先获取两个结果集,然后应用条件。 So you know what is preferred. 所以您知道什么是首选。

  • ON is applied to the set used for creating the permutations of each record as a part of the JOIN operation 将ON应用于创建每个记录的排列的集合, 作为 JOIN操作的一部分
  • WHERE specifies the filter applied after the JOIN operation WHERE指定在JOIN操作之后应用的过滤器

In effect, ON replaces each field that does not satisfy its condition with a NULL. 实际上,ON将不满足其条件的每个字段替换为NULL。 Given the example by @Quassnoi 以@Quassnoi为例

gifts

1   Teddy bear
2   Flowers

sentgifts

1   Alice
1   Bob

---
SELECT  *
FROM    gifts g
LEFT JOIN
        sentgifts sg
ON      g.giftID = sg.giftID

---

The LEFT JOIN permutations would have been calculated for the following collections if there was no ON condition: 如果没有打开条件,则将为以下集合计算左联接的排列:

{ 'Teddy bear': {'ALICE', 'Bob'}, 'Flowers': {'ALICE', 'Bob'} }

with the g.giftID = sg.giftID ON condition, this is the collections that will be used for creating the permutations: g.giftID = sg.giftID ON条件下,这是将用于创建排列的集合:

{ 'Teddy bear': {'ALICE', 'Bob'}, 'Flowers': {NULL, NULL} }

which in effect is: 实际上是:

{ 'Teddy bear': {'ALICE', 'Bob'}, 'Flowers': {NULL} }

and so results in the LEFT JOIN of: 因此导致LEFT JOIN为:

Teddy bear Alice
Teddy bear Bob
Flowers    NULL

and for a FULL OUTER JOIN you would have: 对于完全外部联接,您将具有:

{ 'Teddy bear': {'ALICE', 'Bob'}, 'Flowers': {NULL} } for LEFT JOIN and { 'ALICE': {'Teddy bear', NULL}, 'Flowers': {'Teddy bear', NULL} } for RIGHT JOIN: { 'Teddy bear': {'ALICE', 'Bob'}, 'Flowers': {NULL} }用于左联接和{ 'ALICE': {'Teddy bear', NULL}, 'Flowers': {'Teddy bear', NULL} }表示“ RIGHT JOIN”:

Teddy bear Alice
Teddy bear Bob
Flowers    NULL

If you also had a condition such as ON g.giftID = 1 it would be 如果您还具有ON g.giftID = 1之类的条件,则可能是

{ NULL: {'ALICE', 'Bob'}, 'Flowers': {NULL} }

which for LEFT JOIN would result in 对于LEFT JOIN将导致

Flowers NULL

and for a FULL OUTER JOIN would result in { NULL: {'ALICE', 'Bob'}, 'Flowers': {NULL} } for LEFT JOIN and { 'ALICE': {NULL, NULL}, 'Flowers': {NULL, NULL} } for RIGHT JOIN 而对于FULL OUTER JOIN { NULL: {'ALICE', 'Bob'}, 'Flowers': {NULL} }对于LEFT JOIN则为{ NULL: {'ALICE', 'Bob'}, 'Flowers': {NULL} }对于{ 'ALICE': {NULL, NULL}, 'Flowers': {NULL, NULL} }代表RIGHT JOIN

NULL    Alice
NULL    Bob
Flowers NULL

Note MySQL does not have a FULL OUTER JOIN and you need to apply UNION to LEFT JOIN and RIGHT JOIN 注意 MySQL没有FULL OUTER JOIN,您需要将UNION应用于LEFT JOIN和RIGHT JOIN

If you're using a JOIN, you need to specify the conditions you are joining on. 如果使用的是JOIN,则需要指定要加入的条件。 That list goes in an ON clause. 该列表包含在ON子句中。 A WHERE clause is used to condition data for anywhere in the query. WHERE子句用于条件查询中任何位置的数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM