在 SQL/MySQL 中,join 语句中的“ON”和“WHERE”有啥区别?
Posted
技术标签:
【中文标题】在 SQL/MySQL 中,join 语句中的“ON”和“WHERE”有啥区别?【英文标题】:In SQL / MySQL, what is the difference between "ON" and "WHERE" in a join statement?在 SQL/MySQL 中,join 语句中的“ON”和“WHERE”有什么区别? 【发布时间】:2011-02-12 22:44:22 【问题描述】:以下语句给出相同的结果(一个使用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;
我只能在左外连接的情况下看到“不匹配”的情况: (找出从未有人送过的礼物)
mysql> select name from gifts LEFT OUTER JOIN sentgifts
ON gifts.giftID = sentgifts.giftID
WHERE sentgifts.giftID IS NULL;
在这种情况下,它首先使用on
,然后是where
。 on
是否首先进行匹配,然后 where
进行“二级”过滤?还是有更一般的使用on
与where
的规则?谢谢。
【问题讨论】:
这个问题有两个更好的标题。 【参考方案1】:ON
子句定义了表之间的关系。
WHERE
子句描述了您感兴趣的行。
很多时候你可以交换它们并且仍然得到相同的结果,但是左外连接并不总是这样。
如果ON
子句失败,您仍然会得到一行,其中包含来自 左表,但右表的列中有空值。 如果WHERE
子句失败,您将根本无法获得该行。
【讨论】:
【参考方案2】:WHERE
是整个 SELECT
查询的一部分,ON
是每个单独联接的一部分。
ON
只能引用以前使用过的表的字段。
当左表中的记录没有实际匹配时,LEFT JOIN
从右表返回一条记录,所有字段都设置为NULLS
。 WHERE
子句然后评估并过滤它。
在您的查询中,仅返回来自 gifts
的记录,而 'sentgifts' 中不匹配。
这是一个例子
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
如您所见,没有实际匹配的人可以在sentgifts.id
中留下NULL
,因此只会退回从未发送过的礼物。
【讨论】:
【参考方案3】:当使用INNER JOIN
、ON
和WHERE
将得到相同的结果。所以,
select *
from Table1 t1
inner join Table2 t2 on t1.id = t2.id
where t1.Name = 'John'
将具有与
完全相同的输出select *
from Table1 t1
inner join Table2 t2 on t1.id = t2.id
and t1.Name = 'John'
正如您所指出的,使用OUTER JOIN
时并非如此。构建的查询计划取决于数据库平台和查询细节,并且可能会发生变化,因此仅在此基础上做出决策并不能提供有保证的查询计划。
根据经验,您应该使用在ON
子句中连接表的列和在WHERE
子句中用于过滤的列。这提供了最佳的可读性。
【讨论】:
对比 field1=field2 更复杂的东西使用“ON”是否正确? 是的,经常有多列ON子句。 我的意思是,除了列比较之外,您可以使用复杂的表达式吗? @skan 是的,您可以使用 ON 包含任何条件表达式【参考方案4】:虽然结果相同,但“ON”先进行连接,然后检索连接集的数据。检索速度更快,负载更少。但是使用 'WHERE' 会导致首先获取两个结果集,然后再应用条件。所以你知道什么是首选。
【讨论】:
【参考方案5】: ON 应用于用于创建每个记录的排列的集合作为 JOIN 操作的一部分 WHERE 指定 在 JOIN 操作之后应用的过滤器实际上,ON 将每个不满足其条件的字段替换为 NULL。给定the example by @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
---
如果没有 ON 条件,则会为以下集合计算 LEFT JOIN 排列:
'Teddy bear': 'ALICE', 'Bob', 'Flowers': 'ALICE', 'Bob'
在g.giftID = sg.giftID
ON 条件下,这是将用于创建排列的集合:
'Teddy bear': 'ALICE', 'Bob', 'Flowers': NULL, NULL
实际上是:
'Teddy bear': 'ALICE', 'Bob', 'Flowers': NULL
因此导致左连接:
Teddy bear Alice
Teddy bear Bob
Flowers NULL
对于 FULL OUTER JOIN,您将拥有:
'Teddy bear': 'ALICE', 'Bob', 'Flowers': NULL
用于左连接, 'ALICE': 'Teddy bear', NULL, 'Flowers': 'Teddy bear', NULL
用于右连接:
Teddy bear Alice
Teddy bear Bob
Flowers NULL
如果你也有ON g.giftID = 1
这样的条件,那就是
NULL: 'ALICE', 'Bob', 'Flowers': NULL
对于 LEFT JOIN 会导致
Flowers NULL
对于 FULL OUTER JOIN 会导致
NULL: 'ALICE', 'Bob', 'Flowers': NULL
用于左连接, 'ALICE': NULL, NULL, 'Flowers': NULL, NULL
用于右连接
NULL Alice
NULL Bob
Flowers NULL
注意 MySQL 没有 FULL OUTER JOIN,需要将 UNION 应用于 LEFT JOIN 和 RIGHT JOIN
【讨论】:
【参考方案6】:如果您使用 JOIN,则需要指定您要加入的条件。该列表位于 ON 子句中。 WHERE 子句用于为查询中的任何位置设置数据条件。
【讨论】:
以上是关于在 SQL/MySQL 中,join 语句中的“ON”和“WHERE”有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
SQL语句中的join只能与on连用吗?有没有只用join的?举个例子行吗?