Sql 条件完全外部联接的替代方法
我需要比较两个表中的记录:X和Y。每个记录有两个ID:ID1和ID2。ID1或ID2在两个表中都可以为null,但不能同时为null。我需要生成一个包含两个表中所有信息的视图: 其中X.ID1=Y.ID1和X.ID2=Y.ID2的行 其中X.ID1=Y.ID1但X.ID2为Y.ID2的行 其中X.ID1 Y.ID1但X.ID2=Y.ID2的行 X.ID1和Y.ID1完全不匹配的行 X.ID2和Y.ID2完全不匹配的行 例如:Sql 条件完全外部联接的替代方法,sql,sql-server,Sql,Sql Server,我需要比较两个表中的记录:X和Y。每个记录有两个ID:ID1和ID2。ID1或ID2在两个表中都可以为null,但不能同时为null。我需要生成一个包含两个表中所有信息的视图: 其中X.ID1=Y.ID1和X.ID2=Y.ID2的行 其中X.ID1=Y.ID1但X.ID2为Y.ID2的行 其中X.ID1 Y.ID1但X.ID2=Y.ID2的行 X.ID1和Y.ID1完全不匹配的行 X.ID2和Y.ID2完全不匹配的行 例如: X: Y: |----------
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 |
|---------------------------------------|
我的第一个显而易见的解决方案是进行完全外部联接:
从X.ID1=Y.ID1或X.ID2=Y.ID2上的X完全外部联接Y中选择
这是可行的,但联接中的条件具有糟糕的性能,并且此视图运行可能需要一分钟。删除条件会将执行时间缩短到不到一秒钟,但随后我会丢失其中一个ID的匹配
如何在不使用条件联接的情况下优雅地实现上述功能?我试过:
通过连接两个ID进行连接,但这仅在两个ID匹配时匹配
执行交叉联接并按X.ID1=Y.ID1或X.ID2=Y.ID2进行筛选,但这样会丢失不匹配的案例。这是最有希望的办法。
将所有X和Y进行并集,然后按ID1和ID2进行分组,但这再次仅在两个ID匹配时匹配
您可以尝试将其分解为多个联接。我认为逻辑是:
SELECT …
FROM X JOIN
Y
ON X.ID1 = Y.ID1
UNION ALL
SELECT …
FROM X JOIN
Y
ON X.ID1 <> Y.ID1 AND X.ID2 = Y.ID2
UNION ALL
SELECT ...
FROM X
WHERE NOT EXISTS (SELECT 1 FROM Y WHERE Y.ID1 = X.ID1) AND
NOT EXISTS (SELECT 1 FROM Y WHERE Y.ID2 = X.ID2)
UNION ALL
SELECT ...
FROM Y
WHERE NOT EXISTS (SELECT 1 FROM X WHERE Y.ID1 = X.ID1) AND
NOT EXISTS (SELECT 1 FROM X WHERE Y.ID2 = X.ID2) ;
如果我没看错你的情况,你可以试试这样的。将两个左连接在一起并取两个集合中的一个
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。1 MySQL不支持完全连接,所以我删除了标记。2提供样本数据和期望的结果。谢谢Gordon!这需要对空ID进行更多检查,但我明白了。你认为没有办法减少复制/粘贴的次数吗?很有希望,但这不会返回Y中不在X中的行。更新后也包括Y。