首页 > 解决方案 > 如果一个或多个表中缺少该键,您能否在同一个键上连接三个表?

问题描述

我正在使用三个表并使用相同的主键将它们全部连接在一起,但不能保证所有值都存在于所有三个表中,并且我希望每个值最终都出现在最终连接中。

例如,有一个TableATableBTableC,每个只有一列(我们只称列colAcolBcolC)。值10存在于TableAand中TableC,但不存在TableB

SELECT * FROM TableA FULL OUTER JOIN TableB ON TableA.colA = TableB.colB 
                     FULL OUTER JOIN TableC ON TableB.colB = TableC.colC;

+--------+  +--------+  +--------+
|  colA  |  |  colB  |  |  colC  |
+--------+  +--------+  +--------+
|      5 |  |      5 |  |      5 |
|     10 |  |     15 |  |     10 |
|     15 |  +--------+  |     15 |
+--------+              +--------+

在上面的例子中,我在加入之后得到了这样的结果:

+--------+--------+--------+
|  colA  |  colB  |  colC  |
+--------+--------+--------+
| 5      | 5      | 5      |
| null   | null   | 10     |
| 15     | 15     | 15     |
| 10     | null   | null   |
+--------+--------+--------+

我的预期结果是这样的:

+--------+--------+--------+
|  colA  |  colB  |  colC  |
+--------+--------+--------+
|      5 | 5      |      5 |
|     10 | null   |     10 |
|     15 | 15     |     15 |
+--------+--------+--------+

我加入的逻辑是先加入TableATableB,然后加入结果TableC。在这种特定情况下,联接不起作用。连接可以尝试匹配从通过TableA的列或从的列TableB,但我不知道如何让它同时检查。

因为我是第一次加入TableAand TableB,所以里面没有匹配的值TableB。当我尝试加入TableCTableB,它也找不到匹配项,即使密钥存在于TableA.

我最接近我想要的结果是使用这个查询:

SELECT * FROM TableA FULL OUTER JOIN TableB ON TableA.colA = TableB.colB 
                     RIGHT OUTER JOIN TableC ON TableC.colC IN (TableA.colA, TableB.colB);

+------+  +------+  +------+     +------+------+------+
| colA |  | colB |  | colC |     | colA | colB | colC |
+------+  +------+  +------+     +------+------+------+
|    5 |  |    5 |  |    5 |     | 5    | 5    |    5 |
|   10 |  |   15 |  |   10 | --> | 10   | null |   10 |
|   15 |  |   25 |  |   15 |     | 15   | 15   |   15 |
+------+  +------+  |   20 |     | null | null |   20 |
                    +------+     +------+------+------+

预期结果:

+------+------+------+
| colA | colB | colC |
+------+------+------+
| 5    | 5    | 5    |
| 10   | null | 10   |
| 15   | 15   | 15   |
| null | null | 20   |
| null | 25   | null |
+------+------+------+

不幸的是,这不包括仅存在于最终连接表中TableATableB中的值,这就是我首先使用的原因FULL OUTER JOIN。使用FULL OUTER JOIN,我不能使用该IN子句。有什么解决方案可以满足我的需求吗?

DB小提琴:https ://www.db-fiddle.com/f/faMLh4EAAKfBotXbaDofaQ/1

标签: sqlpostgresqljoin

解决方案


这是一个演示完全三路完全外连接的版本。成功的查询将返回七行:

+------+ +------+ +------+ +------+------+------+
| 科尔A | | 科尔B | | 科尔C | | 科尔A | 科尔B | 科尔C |
+------+ +------+ +------+ +------+------+------+
| 1 | | 2 | | 4 | | 1 | 空 | 空 |
| 3 | | 3 | | 5 | --> | 空 | 2 | 空 |
| 5 | | 6 | | 6 | | 3 | 3 | 空 |
| 7 | | 7 | | 7 | | 空 | 空 | 4 |
+------+ +------+ +------+ | 5 | 空 | 5 |
                                 | 空 | 6 | 6 |
                                 | 7 | 7 | 7 |
                                 +-----+------+------+
select ColA, ColB, ColC
  from TableA
  full join TableB
    on ColA=ColB
  full join TableC
    on ColC=coalesce(ColA, ColB)
order by coalesce(ColA, ColB, ColC);

秘密在于coalesce每个附加表的连接条件中的先前表键。

你可以在这里看到它的作用


推荐阅读