在阅读它之后,这不是显式与隐式SQL连接的副本。 答案可能相关(甚至相同),但问题是不同的。


它们之间有什么不同?每一种都应该有什么不同?

如果我正确地理解了这个理论,那么查询优化器应该能够互换地使用这两种方法。


当前回答

对于内部连接,WHERE和ON可以互换使用。事实上,可以在相关子查询中使用ON。例如:

update mytable
set myscore=100
where exists (
select 1 from table1
inner join table2
on (table2.key = mytable.key)
inner join table3
on (table3.key = table2.key and table3.key = table1.key)
...
)

这(恕我直言)完全让人困惑,而且很容易忘记将table1链接到任何东西(因为“driver”表没有“on”子句),但这是合法的。

其他回答

当涉及到左连接时,where子句和on子句之间有很大的区别。

这里有一个例子:

mysql> desc t1; 
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | NULL    |       |
| fid   | int(11)     | NO   |     | NULL    |       |
| v     | varchar(20) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+

fid是表t2的id。

mysql> desc t2;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int(11)     | NO   |     | NULL    |       |
| v     | varchar(10) | NO   |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

查询“on子句”:

mysql> SELECT * FROM `t1` left join t2 on fid = t2.id AND t1.v = 'K' 
    -> ;
+----+-----+---+------+------+
| id | fid | v | id   | v    |
+----+-----+---+------+------+
|  1 |   1 | H | NULL | NULL |
|  2 |   1 | B | NULL | NULL |
|  3 |   2 | H | NULL | NULL |
|  4 |   7 | K | NULL | NULL |
|  5 |   5 | L | NULL | NULL |
+----+-----+---+------+------+
5 rows in set (0.00 sec)

where子句查询:

mysql> SELECT * FROM `t1` left join t2 on fid = t2.id where t1.v = 'K';
+----+-----+---+------+------+
| id | fid | v | id   | v    |
+----+-----+---+------+------+
|  4 |   7 | K | NULL | NULL |
+----+-----+---+------+------+
1 row in set (0.00 sec)

很明显, 第一个查询从t1返回一条记录,从t2返回与t1相关的行(如果有的话)。v = 'K'。

第二个查询返回来自t1的行,但只针对t1。v = 'K'将有任何与它相关的行。

就优化器而言,使用ON或WHERE定义连接子句应该没有区别。

然而,恕我直言,我认为在执行连接时使用ON子句更清楚。这样,您就有了查询的特定部分,该部分规定了如何处理连接,而不是与其余WHERE子句混合。

在INNER join中,它们是可互换的,优化器会随意重新排列它们。

在OUTER连接上,它们不一定是可互换的,这取决于它们所依赖的连接的哪一侧。

我把它们放在任意一个位置,取决于可读性。

为了获得更好的性能,表应该有一个用于join的特殊索引列。

所以如果你的条件列不是那些索引列之一,那么我怀疑最好把它保存在WHERE。

所以你使用索引列来JOIN,然后在JOIN之后你在无索引列上运行条件。

它们不是一回事。

考虑一下这些问题:

SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID
WHERE Orders.ID = 12345

and

SELECT *
FROM Orders
LEFT JOIN OrderLines ON OrderLines.OrderID=Orders.ID 
    AND Orders.ID = 12345

第一个将返回订单及其行(如果有的话),订单号为12345。 第二个将返回所有订单,但只有订单12345有与之关联的行。

使用INNER JOIN,这两个子句实际上是等效的。然而,仅仅因为它们在功能上相同,产生相同的结果,并不意味着这两种子句具有相同的语义。