Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 条件完全外部联接的替代方法_Sql_Sql Server - Fatal编程技术网

Sql 条件完全外部联接的替代方法

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。每个记录有两个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:
|---------------|    |---------------|
|  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。