TL;博士
INNER JOIN 语句可以重写为 CROSS JOIN,其 WHERE 子句与您在 INNER JOIN 查询的 ON 子句中使用的条件匹配。
表关系
考虑到我们有以下post
和post_comment
表格:
有以下post
记录:
| id | title |
|----|-----------|
| 1 | Java |
| 2 | Hibernate |
| 3 | JPA |
并且post_comment
具有以下三行:
| id | review | post_id |
|----|-----------|---------|
| 1 | Good | 1 |
| 2 | Excellent | 1 |
| 3 | Awesome | 2 |
SQL 内连接
SQL JOIN 子句允许您关联属于不同表的行。例如,CROSS JOIN将创建一个笛卡尔积,其中包含两个连接表之间所有可能的行组合。
虽然 CROSS JOIN 在某些情况下很有用,但大多数时候,您希望根据特定条件连接表。而且,这就是 INNER JOIN 发挥作用的地方。
SQL INNER JOIN 允许我们根据通过 ON 子句指定的条件过滤连接两个表的笛卡尔积。
SQL INNER JOIN - 在“始终为真”条件下
如果您提供“始终为真”条件,则 INNER JOIN 不会过滤连接的记录,结果集将包含两个连接表的笛卡尔积。
例如,如果我们执行以下 SQL INNER JOIN 查询:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 1
我们将得到所有的组合post
和post_comment
记录:
| p.id | pc.id |
|---------|------------|
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
因此,如果 ON 子句条件为“始终为真”,则 INNER JOIN 就等同于 CROSS JOIN 查询:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 1
ORDER BY p.id, pc.id
SQL INNER JOIN - ON“总是假”条件
另一方面,如果 ON 子句条件为“始终为假”,则所有连接的记录都将被过滤掉,结果集将为空。
因此,如果我们执行以下 SQL INNER JOIN 查询:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
INNER JOIN post_comment pc ON 1 = 0
ORDER BY p.id, pc.id
我们不会得到任何结果:
| p.id | pc.id |
|---------|------------|
这是因为上面的查询等价于下面的 CROSS JOIN 查询:
SELECT
p.id AS "p.id",
pc.id AS "pc.id"
FROM post p
CROSS JOIN post_comment
WHERE 1 = 0
ORDER BY p.id, pc.id
SQL INNER JOIN - 使用外键和主键列的 ON 子句
最常见的 ON 子句条件是子表中的外键列与父表中的主键列匹配的条件,如以下查询所示:
SELECT
p.id AS "p.id",
pc.post_id AS "pc.post_id",
pc.id AS "pc.id",
p.title AS "p.title",
pc.review AS "pc.review"
FROM post p
INNER JOIN post_comment pc ON pc.post_id = p.id
ORDER BY p.id, pc.id
在执行上述 SQL INNER JOIN 查询时,我们得到以下结果集:
| p.id | pc.post_id | pc.id | p.title | pc.review |
|---------|------------|------------|------------|-----------|
| 1 | 1 | 1 | Java | Good |
| 1 | 1 | 2 | Java | Excellent |
| 2 | 2 | 3 | Hibernate | Awesome |
因此,只有符合 ON 子句条件的记录才会包含在查询结果集中。在我们的例子中,结果集包含所有post
以及它们的post_comment
记录。post
没有关联的行post_comment
被排除,因为它们不能满足 ON 子句条件。
同样,上面的 SQL INNER JOIN 查询等价于下面的 CROSS JOIN 查询:
SELECT
p.id AS "p.id",
pc.post_id AS "pc.post_id",
pc.id AS "pc.id",
p.title AS "p.title",
pc.review AS "pc.review"
FROM post p, post_comment pc
WHERE pc.post_id = p.id
未命中的行是满足 WHERE 子句的行,只有这些记录才会包含在结果集中。这是可视化 INNER JOIN 子句如何工作的最佳方式。
| p.id | pc.post_id | pc.id | p.title | 电脑评论 |
|--------|------------|--------|-----------|--------- --|
| 1 | 1 | 1 | 爪哇 | 好 |
| 1 | 1 | 2 | 爪哇 | 优秀 |
| 1 | 2 | 3 | 爪哇 | 真棒|
| 2 | 1 | 1 | 休眠 | 好 |
| 2 | 1 | 2 | 休眠 | 优秀 |
| 2 | 2 | 3 | 休眠 | 真棒|
| 3 | 1 | 1 | JPA | 好 |
| 3 | 1 | 2 | JPA | 优秀 |
| 3 | 2 | 3 | JPA | 真棒|
并不是说这仅适用于 INNER JOIN,不适用于 OUTER JOIN。