Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/86.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_Tsql_Full Outer Join - Fatal编程技术网

Sql 基于多个字段的完全外部联接

Sql 基于多个字段的完全外部联接,sql,tsql,full-outer-join,Sql,Tsql,Full Outer Join,以下是我面临的情况: 我有两个表A和B。如果记录在表A中而不在表B中,则需要将它们添加到表B中。如果记录在表B中而不在表A中,则需要将它们从表B中删除。这里的诀窍是,正是两个键的混合构成了唯一的组合 Table A Operation_Key Part_Key 1 1 1 2 2 1 2 3 Table B Operation_Key Part_Key

以下是我面临的情况:

我有两个表A和B。如果记录在表A中而不在表B中,则需要将它们添加到表B中。如果记录在表B中而不在表A中,则需要将它们从表B中删除。这里的诀窍是,正是两个键的混合构成了唯一的组合

Table A    
Operation_Key    Part_Key  
1                1
1                2
2                1
2                3

Table B
Operation_Key    Part_Key  Record_Key
1                1         1
2                1         2
2                3         3
2                4         4
我正在尝试获取正确的查询类型,以便返回的结果如下所示

Results
Operation_Key        Part_Key  Record_Key   Action
1                    2         NULL         Add
2                    4         4            Delete
到目前为止,我的查询与此类似:

CREATE TABLE #Action_Table
(
  Action VARCHAR(6),
  Action_Bit INT,
  Operation_Key INT,
  Record_Key INT,
  Part_Key INT
)
INSERT INTO #Action_Table
SELECT 
  CASE
    WHEN WS.Operation_Key IS NULL THEN 'Delete'
    WHEN WS.Operation_Key IS NOT NULL THEN 'Add'
  END Action,
  CASE
    WHEN WS.Operation_Key IS NULL THEN '0'
    WHEN WS.Operation_Key IS NOT NULL THEN '1'
  END Action_Bit,
  CASE
    WHEN WS.Operation_Key IS NULL THEN WC.Operation_Key
    WHEN WS.Operation_Key IS NOT NULL THEN WS.Operation_Key
  END Operation_Key,
  CASE
    WHEN WS.Operation_Key IS NULL THEN WC.Record_Key
    WHEN WS.Operation_Key IS NOT NULL THEN NULL
  END Workcenter_Component_Key,
  CASE
    WHEN WS.Operation_Key IS NULL THEN WC.Part_Key
    WHEN WS.Operation_Key IS NOT NULL THEN WS.Part_Key
  END Part_Key
FROM #WS_Part_Table WS
FULL OUTER JOIN #WC_Part_Table WC
  ON WC.Part_Key = WS.Part_Key
 AND WC.Operation_Key = WS.Operation_Key
WHERE (WS.Part_Key IS NULL or WC.Part_Key IS NULL) AND (WS.Operation_Key IS NULL or WC.Operation_Key IS NULL)
#WS#u Part#表和#WC#u Part#表都是我正在使用查询构建的临时表,但我的困境是我必须在我感兴趣的操作键上预查询WC#u Part#表查询,否则我会得到太多的结果

这是我用来创建#WC#u Part#表的查询

    CREATE TABLE #WC_Part_Table
    (
      Operation_Key INT,
      Record_Key INT,
      Part_Key INT
    )
    -- Workcenter Component Table
    INSERT INTO #WC_Part_Table
    SELECT
      O.Operation_Key,
      WC.Record_Key,
      WC.Part_Key
    FROM Workcenter_Component WC
    JOIN Operation O
      ON O.Default_Workcenter_Key = WC.Workcenter_Key

 /* There is some reason why this next line is needed */
    WHERE O.Operation_Key = 23149
添加到B:

insert into B (Operation_Key, Part_Key, Record_Key)
values
select Operation_Key, Part_Key, null as Record_Key from A
left join b on a.Operation_Key = b.Operation_Key and
a.Part_Key = b.Part_Key
where b.Part_Key is null
从B中删除:

Delete from B
select * from B left join A on b.Operation_Key = a.Operation_Key and
    b.Part_Key = a.Part_Key
where a.Operation_Key is null

Tyr此选项可获取您发布的结果:

SELECT COALESCE(a.Operation_Key, b.Operation_Key) Operation_Key,
             COALESCE(a.Part_Key, b.Part_Key) Part_Key,
             Record_Key,
             CASE 
                WHEN Record_Key IS NULL THEN 'Add'
                ELSE 'Delete'
            END Action
  FROM TableA a FULL OUTER JOIN TableB b
      ON a.Operation_Key = b.Operation_Key
        AND a.Part_Key = b.Part_Key
 WHERE (a.Operation_Key IS NULL) OR (b.Operation_Key IS NULL)
测试脚本:

CREATE TABLE #TableA     
(       
    Operation_Key INT,       
    Part_Key INT
) 

INSERT INTO #TableA
SELECT 1,1 
UNION
SELECT 1,2 
UNION
SELECT 2,1 
UNION
SELECT 2,3 

CREATE TABLE #TableB
(       
    Operation_Key INT,       
    Part_Key INT,
    Record_Key INT
) 

INSERT INTO #TableB
SELECT 1,1,1 
UNION
SELECT  2,1,2
UNION
SELECT 2,3,3 
UNION
SELECT 2,4,4 


SELECT  COALESCE(a.Operation_Key, b.Operation_Key) Operation_Key,              
                COALESCE(a.Part_Key, b.Part_Key) Part_Key,              
                Record_Key,              
                CASE                  
                    WHEN Record_Key IS NULL THEN 'Add'                 
                    ELSE 'Delete'             
                END Action   
    FROM    #TableA a FULL OUTER JOIN #TableB b       
        ON  a.Operation_Key = b.Operation_Key         
     AND    a.Part_Key = b.Part_Key  
 WHERE (a.Operation_Key IS NULL) OR (b.Operation_Key IS NULL) 
Operation_Key   Part_Key    Record_Key  Action
1   2   NULL    Add
2   4   4   Delete
输出:

CREATE TABLE #TableA     
(       
    Operation_Key INT,       
    Part_Key INT
) 

INSERT INTO #TableA
SELECT 1,1 
UNION
SELECT 1,2 
UNION
SELECT 2,1 
UNION
SELECT 2,3 

CREATE TABLE #TableB
(       
    Operation_Key INT,       
    Part_Key INT,
    Record_Key INT
) 

INSERT INTO #TableB
SELECT 1,1,1 
UNION
SELECT  2,1,2
UNION
SELECT 2,3,3 
UNION
SELECT 2,4,4 


SELECT  COALESCE(a.Operation_Key, b.Operation_Key) Operation_Key,              
                COALESCE(a.Part_Key, b.Part_Key) Part_Key,              
                Record_Key,              
                CASE                  
                    WHEN Record_Key IS NULL THEN 'Add'                 
                    ELSE 'Delete'             
                END Action   
    FROM    #TableA a FULL OUTER JOIN #TableB b       
        ON  a.Operation_Key = b.Operation_Key         
     AND    a.Part_Key = b.Part_Key  
 WHERE (a.Operation_Key IS NULL) OR (b.Operation_Key IS NULL) 
Operation_Key   Part_Key    Record_Key  Action
1   2   NULL    Add
2   4   4   Delete

通过巧妙地使用SQL“COALESCE”操作符,您可以准确地获得所需的结果表(查看示例设置)。如果使用如下查询:

SELECT
    COALESCE(A.Operation_Key, B.Operation_Key) as Operation_Key,
    COALESCE(A.part_key, B.part_key) as Part_Key,
    B.Record_Key,
    CASE WHEN A.Operation_Key IS NULL THEN
        'Delete'
    ELSE
        'Add'
    END AS [Action] FROM A
FULL OUTER JOIN B 
    ON A.Operation_Key = B.Operation_Key 
        AND A.Part_Key= B.Part_Key
WHERE A.Operation_Key IS NULL 
    OR B.Operation_Key IS NULL

…您将得到一个与示例完全相同的结果表。

您使用的是什么RDBMS和版本?。。。顺便问一下,您需要一个解释您的操作的查询吗?难道您不能删除或添加一行吗?这个查询是为了生成一个报告,让一个人进入并进行编辑(说来话长)。不用说,我没有直接访问数据库的权限来添加/插入/更新/删除记录,只是查询并告诉其他人该怎么做。哦,这有点混乱……那么你应该使用@Cybernate的答案。如果你有
WC\u Part\u表
WS\u Part\u表
作为
视图
,而不使用
WHERE O.Operation\u Key=23149
条件,你可能会发现更好。然后你可以使用KenTaylor或Cybernate的视图(如果你想手动检查,结果太多,你可以添加任何这样的条件)。我认为他希望生成一个“软插入”或“软删除”表。您的查询应该可以做到这一点,他可以将它们合并在一起并添加“添加”或“删除”列。重新编写查询以利用合并功能,但它仍然不起作用。我得到了所有的添加记录,没有删除记录。另外,添加记录包括表中已经存在的所有记录。@NA Slacker:我已经添加了用于检查查询的测试脚本,并根据需要获得了结果。请检查记录键字段上的“案例”陈述是否存在问题;要正确分配“添加”或“删除”,应在字段A.Operation\u键或A.Part\u键上。如前所述,测试B表上的任何字段都会反转添加和删除操作。看到我对这个问题的回答了吗…@Ken:我认为可以使用记录的Null值来确定是否应该添加或删除记录。我已经发布了获得所需输出的测试脚本和结果。@Cybermate:你是对的;我倒着读你的逻辑。:-)完全取决于测试和排序结果的方式。我投票赞成你的答案;我想我们是第一次同时发布的。数据中肯定还有其他东西我无法识别,因为一旦我预筛选了一个数据表,我就可以使用原始查询和合并函数得到我想要的结果。@NA Slacker:预筛选数据表是什么意思。你能详细解释一下吗?@NA Slacker:字段PART_KEY和OPERATION_KEY在数据中已经有空值了吗?应该没有,但我想可能是这样的。我要花点时间来研究这个问题。谢谢你的帮助。我知道我很接近。