首页 > 解决方案 > 有条件的完全外连接的替代方案

问题描述

我需要比较两个表中的记录:X 和 Y。每条记录都有两个 ID:ID1 和 ID2。ID1 或 ID2 在任一表中都可以为空,但不能同时为空。我需要生成一个包含两个表中所有信息的视图:

例子:

X:                   Y:
|---------------|    |---------------|
|  ID1  |  ID2  |    |  ID1  |  ID2  |
|---------------|    |---------------|
|   1   |   A   |    |   1   |   A   |
|   2   |   B   |    |   2   |   C   |
|   3   | NULL  |    | NULL  |   B   |
| NULL  |   D   |    |   5   | NULL  |
|---------------|    |---------------|

Output:
|---------------------------------------|
|  XID1 |  YID1 |  XID2 |  YID2 |  SRC  |
|---------------------------------------|
|   1   |   1   |   A   |   A   |  X+Y  |
|   2   |   2   |   B   |   C   |  X+Y  |
|   3   | NULL  | NULL  | NULL  |   X   |
| NULL  |   5   | NULL  | NULL  |   Y   |
|   2   | NULL  |   B   |   B   |  X+Y  |
| NULL  |   2   | NULL  |   C   |   Y   |
| NULL  | NULL  |   D   | NULL  |   X   |
|---------------------------------------|

我的第一个明显的解决方案是做一个FULL OUTER JOIN

SELECT … FROM X FULL OUTER JOIN Y ON X.ID1 = Y.ID1 OR X.ID2 = Y.ID2

这行得通,但是连接中的条件性能很差,并且该视图最多需要一分钟才能运行。删除条件将执行时间缩短到不到一秒,但随后我失去了其中一个 ID 的匹配。

在不使用条件连接的情况下如何优雅地实现上述目标?我试过了:

标签: sqlsql-server

解决方案


如果我正确阅读了您的条件,您可以尝试这样的事情。将左边的两个连接在一起并取两个集合中的一个不同的集合。

SELECT DISTINCT ... FROM (
  SELECT … FROM X LEFT JOIN Y ON X.ID1 = Y.ID1
  UNION ALL
  SELECT … FROM X LEFT JOIN Y ON X.ID2 = Y.ID2
  UNION ALL
  SELECT … FROM Y LEFT JOIN X ON Y.ID1 = X.ID1 WHERE X.ID1 is null
  UNION ALL
  SELECT … FROM Y LEFT JOIN X ON Y.ID2 = X.ID2 WHERE X.ID2 is null
)

在我必须在连接中进行 OR 或两个左连接的联合之间进行选择的情况下,我发现联合更快。

编辑:更新为在左侧也包含 Y。


推荐阅读