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


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

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


当前回答

关于你的问题,

只要你的服务器能得到它,内部连接的'on'和'where'都是一样的:

select * from a inner join b on a.c = b.c

and

select * from a inner join b where a.c = b.c

并非所有口译员都知道“where”选项,所以可能应该避免使用。当然,“on”从句更清楚。

其他回答

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

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

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

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

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

关于你的问题,

只要你的服务器能得到它,内部连接的'on'和'where'都是一样的:

select * from a inner join b on a.c = b.c

and

select * from a inner join b where a.c = b.c

并非所有口译员都知道“where”选项,所以可能应该避免使用。当然,“on”从句更清楚。

让我们考虑一下这些表格:

A

id | SomeData

B

id | id_A | SomeOtherData

id_A是表a的外键

写这个查询:

SELECT *
FROM A
LEFT JOIN B
ON A.id = B.id_A;

将提供如下结果:

/ : part of the result
                                       B
                      +---------------------------------+
            A         |                                 |
+---------------------+-------+                         |
|/////////////////////|///////|                         |
|/////////////////////|///////|                         |
|/////////////////////|///////|                         |
|/////////////////////|///////|                         |
|/////////////////////+-------+-------------------------+
|/////////////////////////////|
+-----------------------------+

A中有而B中没有的东西意味着B中有空值。


现在,让我们考虑B.id_A中的一个特定部分,并从前面的结果中突出显示它:

/ : part of the result
* : part of the result with the specific B.id_A
                                       B
                      +---------------------------------+
            A         |                                 |
+---------------------+-------+                         |
|/////////////////////|///////|                         |
|/////////////////////|///////|                         |
|/////////////////////+---+///|                         |
|/////////////////////|***|///|                         |
|/////////////////////+---+---+-------------------------+
|/////////////////////////////|
+-----------------------------+

写这个查询:

SELECT *
FROM A
LEFT JOIN B
ON A.id = B.id_A
AND B.id_A = SpecificPart;

将提供如下结果:

/ : part of the result
* : part of the result with the specific B.id_A
                                       B
                      +---------------------------------+
            A         |                                 |
+---------------------+-------+                         |
|/////////////////////|       |                         |
|/////////////////////|       |                         |
|/////////////////////+---+   |                         |
|/////////////////////|***|   |                         |
|/////////////////////+---+---+-------------------------+
|/////////////////////////////|
+-----------------------------+

因为这将在内部连接中删除不在B.id_A = SpecificPart中的值


现在,让我们把查询改为这样:

SELECT *
FROM A
LEFT JOIN B
ON A.id = B.id_A
WHERE B.id_A = SpecificPart;

结果是:

/ : part of the result
* : part of the result with the specific B.id_A
                                       B
                      +---------------------------------+
            A         |                                 |
+---------------------+-------+                         |
|                     |       |                         |
|                     |       |                         |
|                     +---+   |                         |
|                     |***|   |                         |
|                     +---+---+-------------------------+
|                             |
+-----------------------------+

因为整个结果是根据B. id_a = SpecificPart过滤的,删除了B. id_a为NULL的部分,这些部分在A中,但不在B中

这就是我的解。

SELECT song_ID,songs.fullname, singers.fullname
FROM music JOIN songs ON songs.ID = music.song_ID  
JOIN singers ON singers.ID = music.singer_ID
GROUP BY songs.fullname

你必须有GROUP BY才能让它工作。

希望这对你有所帮助。