代码之家  ›  专栏  ›  技术社区  ›  Jon Davis Glenn Block

在一个公共表上联接,如何获得一个完整的外部联接以在另一个表上展开?

  •  3
  • Jon Davis Glenn Block  · 技术社区  · 14 年前

    我已经搜索了StackOverflow和Google来寻找这个问题的答案。

    我有三张桌子。第一个表定义了一个公共键,比如“CompanyID”。另外两个表有时有一个公共字段,比如“EmployeeName”。

    CompanyID | TableA    | TableB
    12        | John Doe  | John Doe
    12        | Betty Sue | NULL
    12        | NULL      | Billy Bob
    

    SELECT Company.CompanyID,
        TableA.EmployeeName,
        TableB.EmployeeName
    FROM Company
    FULL OUTER JOIN TableA ON Company.CompanyID = TableA.CompanyID
    FULL OUTER JOIN TableB ON 
        Company.CompanyID = TableB.CompanyID AND 
        (TableA.EmployeeName IS NULL OR TableB.EmployeeName IS NULL OR TableB.EmployeeName = TableA.EmployeeName)
    

    我只从一个匹配的表中获取空值,而不获取另一个表的扩展。在上面的示例中,我基本上只得到第一行和第三行,而不是第二行。

    有人能帮我创建这个查询,并告诉我这是如何正确完成的吗?

    顺便说一句,我已经有一个看起来非常干净的存储过程,并填充内存中的表,但这不是我想要的。

    --编辑:

    这是一个完整的运行样本什么 目前没有

    DECLARE @Company TABLE
    (
        CompanyID int
    )
    
    INSERT INTO @Company (CompanyID) VALUES (10)
    INSERT INTO @Company (CompanyID) VALUES (12)
    
    DECLARE @TableA TABLE
    (
        EmployeeId int,
        CompanyId int,
        EmployeeName varchar(30)
    )
    
    DECLARE @TableB TABLE
    (
        EmployeeId int,
        CompanyId int,
        EmployeeName varchar(30)
    )
    
    INSERT INTO @TableA ( EmployeeId, CompanyId, EmployeeName )
    VALUES ( 1, 10, 'someone' )
    
    --INSERT INTO @TableA ( EmployeeId, CompanyId, EmployeeName )
    --VALUES ( 2, 12, 'someone 2' )
    
    INSERT INTO @TableA ( EmployeeId, CompanyId, EmployeeName )
    VALUES ( 3, 12, 'someone 3' )
    
    INSERT INTO @TableA ( EmployeeId, CompanyId, EmployeeName )
    VALUES ( 3, 12, 'someone 4' )
    
    INSERT INTO @TableB ( EmployeeId, CompanyId, EmployeeName )
    VALUES ( 1, 10, 'someone' )
    
    INSERT INTO @TableB ( EmployeeId, CompanyId, EmployeeName )
    VALUES ( 2, 12, 'someone 2' )
    
    --INSERT INTO @TableB ( EmployeeId, CompanyId, EmployeeName )
    --VALUES ( 3, 12, 'someone 3' )
    
    INSERT INTO @TableB ( EmployeeId, CompanyId, EmployeeName )
    VALUES ( 3, 12, 'someone 4' )
    
    SELECT Company.CompanyID,
        TableA.EmployeeName,
        TableB.EmployeeName
    FROM @Company Company
    FULL OUTER JOIN @TableA TableA ON Company.CompanyID = TableA.CompanyID
    FULL OUTER JOIN @TableB TableB ON Company.CompanyID = TableB.CompanyID
    WHERE
    (
        TableA.EmployeeName IS NULL OR TableB.EmployeeName IS NULL OR 
        TableB.EmployeeName = TableA.EmployeeName
    )
    AND Company.CompanyID = 12
    

    结果:

    CompanyID   EmployeeName    EmployeeName
    12          someone 4       someone 4
    

    我想要的是:

    CompanyID   EmployeeName    EmployeeName
    12          NULL            someone 2
    12          someone 3       NULL
    12          someone 4       someone 4
    
    4 回复  |  直到 14 年前
        1
  •  1
  •   Dimitris Baltas    14 年前

    完全外部联接只能在companyID和employeeName上的TableA和TableB之间进行,因为这是一个值,如果它只存在于一个表中,则希望填充为NULL。

    完全外部连接解决方案:

    select Company.companyID, EmployeeNameA, EmployeeNameB
    from (
        SELECT isnull(TableA.CompanyID, TableB.CompanyID) as companyID,
            TableA.EmployeeName as EmployeeNameA,
            TableB.EmployeeName as EmployeeNameB
        FROM @TableA TableA 
        FULL OUTER JOIN @TableB TableB ON TableA.EmployeeName = TableB.EmployeeName and TableA.companyID = TableB.companyID
        WHERE
         TableA.CompanyID = 12 or TableB.CompanyID = 12 
    ) merged
    inner join @Company Company
        on merged.companyID = Company.companyID
    

    就我个人而言,我觉得很难用完全的外部连接来思考。我的方法是:通过在受影响的表之间进行并集,在结果中找到所需的不同EmployeeNames,然后使用左联接从两个表中获取数据,从而在需要时获得null。

    左连接示例:

    select c.companyID, a.employeeName, b.employeeName
    from  (
        select distinct employeeName, companyID
        from  (
            select a.employeeName, companyID 
            from @tableA  a
            union 
            select b.employeeName, companyID
            from @tableB b
        ) a
    ) z
    inner join @company c
        on c.companyID = z.companyID
    left join @tableA  a
        on z.companyID = a.companyID and z.employeeName = a.employeeName
    left join @tableB  b
        on z.companyID = b.companyID and z.employeeName = b.employeeName
    where z.companyID = 12
    
        2
  •  2
  •   KM.    14 年前

    SELECT Company.CompanyID,
        TableA.EmployeeName,
        TableB.EmployeeName
    FROM Company
    LEFT OUTER JOIN TableA ON Company.CompanyID = TableA.CompanyID
    LEFT OUTER JOIN TableB ON Company.CompanyID = TableB.CompanyID
    WHERE (TableA.EmployeeName IS NULL OR TableB.EmployeeName IS NULL OR TableB.EmployeeName = TableA.EmployeeName)
    

    运算后给出了测试数据和预期结果集

    试试这个(问题中的表格和测试数据):

    DECLARE @Company TABLE (CompanyID int)
    DECLARE @TableA TABLE (EmployeeId int,CompanyId int,EmployeeName varchar(30))
    DECLARE @TableB TABLE (EmployeeId int,CompanyId int,EmployeeName varchar(30))
    
    set nocount on
    INSERT INTO @Company (CompanyID) VALUES (10)
    INSERT INTO @Company (CompanyID) VALUES (12)
    
    --INSERT INTO @TableA ( EmployeeId, CompanyId, EmployeeName )--VALUES ( 2, 12, 'someone 2' )
    INSERT INTO @TableA ( EmployeeId, CompanyId, EmployeeName )VALUES ( 1, 10, 'someone' )
    INSERT INTO @TableA ( EmployeeId, CompanyId, EmployeeName )VALUES ( 3, 12, 'someone 3' )
    INSERT INTO @TableA ( EmployeeId, CompanyId, EmployeeName )VALUES ( 3, 12, 'someone 4' )
    
    --INSERT INTO @TableB ( EmployeeId, CompanyId, EmployeeName )--VALUES ( 3, 12, 'someone 3' )
    INSERT INTO @TableB ( EmployeeId, CompanyId, EmployeeName )VALUES ( 1, 10, 'someone' )
    INSERT INTO @TableB ( EmployeeId, CompanyId, EmployeeName )VALUES ( 2, 12, 'someone 2' )
    INSERT INTO @TableB ( EmployeeId, CompanyId, EmployeeName )VALUES ( 3, 12, 'someone 4' )
    set nocount off
    
    SELECT coalesce(TableA.CompanyID,TableB.CompanyID) CompanyID,
        TableA.EmployeeName,
        TableB.EmployeeName
    FROM @TableA TableA
    FULL OUTER jOIN  @TableB TableB ON TableA.CompanyID = TableB.CompanyID AND TableB.EmployeeName = TableA.EmployeeName
    WHERE coalesce(TableA.CompanyID,TableB.CompanyID) = 12
    

    输出:

    CompanyID   EmployeeName                   EmployeeName
    ----------- ------------------------------ ------------------------------
    12          NULL                           someone 2
    12          someone 3                      NULL
    12          someone 4                      someone 4
    
    (3 row(s) affected)
    
        3
  •  1
  •   HLGEM    14 年前

    DECLARE @Company TABLE 
    ( 
        CompanyID int 
    ) 
    
    INSERT INTO @Company (CompanyID) VALUES (10) 
    INSERT INTO @Company (CompanyID) VALUES (12) 
    
    DECLARE @TableA TABLE 
    ( 
        EmployeeId int, 
        CompanyId int, 
        EmployeeName varchar(30) 
    ) 
    
    DECLARE @TableB TABLE 
    ( 
        EmployeeId int, 
        CompanyId int, 
        EmployeeName varchar(30) 
    ) 
    
    INSERT INTO @TableA ( EmployeeId, CompanyId, EmployeeName ) 
    VALUES ( 1, 10, 'someone' ) 
    
    --INSERT INTO @TableA ( EmployeeId, CompanyId, EmployeeName ) 
    --VALUES ( 2, 12, 'someone 2' ) 
    
    INSERT INTO @TableA ( EmployeeId, CompanyId, EmployeeName ) 
    VALUES ( 3, 12, 'someone 3' ) 
    
    INSERT INTO @TableA ( EmployeeId, CompanyId, EmployeeName ) 
    VALUES ( 3, 12, 'someone 4' ) 
    
    INSERT INTO @TableB ( EmployeeId, CompanyId, EmployeeName ) 
    VALUES ( 1, 10, 'someone' ) 
    
    INSERT INTO @TableB ( EmployeeId, CompanyId, EmployeeName ) 
    VALUES ( 2, 12, 'someone 2' ) 
    
    --INSERT INTO @TableB ( EmployeeId, CompanyId, EmployeeName ) 
    --VALUES ( 3, 12, 'someone 3' ) 
    
    INSERT INTO @TableB ( EmployeeId, CompanyId, EmployeeName ) 
    VALUES ( 3, 12, 'someone 4' ) 
    
    INSERT INTO @TableB ( EmployeeId, CompanyId, EmployeeName )  
    VALUES ( 3, 12, 'someone 4' )  
    
    SELECT Company.CompanyID,  
       A.EmployeeNameTableA,  
       A.EmployeeNameTAbleB 
    FROM @Company Company  
    left OUTER JOIN (select TableA.EmployeeName as EmployeeNameTableA, TableB.EmployeeName as EmployeeNameTableB , 
    coalesce(TableA.CompanyID,TableB.CompanyID) as CompanyID 
    from @TableA TableA  
    FULL OUTER JOIN @TableB TableB ON TableA.CompanyID = TableB.CompanyID and TableB.EmployeeName = TableA.EmployeeName and (tablea.companyid = 12 or tableb.companyid = 12))A ON Company.CompanyID = A.CompanyID  
    
    WHERE Company.CompanyID = 12  
    
        4
  •  0
  •   Jon Davis Glenn Block    14 年前

    SELECT Company.CompanyID,
        TableA.EmployeeName as EmployeeNameTableA,
        TableB.EmployeeName as EmployeeNameTableB
    FROM @TableA TableA 
    FULL OUTER JOIN @TableB TableB ON TableA.EmployeeName = TableB.EmployeeName 
        and TableA.companyID = TableB.companyID
    INNER JOIN @Company Company ON (
        Company.CompanyID = TableA.CompanyId OR Company.CompanyID = TableB.CompanyId
    )
    WHERE Company.CompanyID = 12
    

    我想我最终要做的就是继续使用存储过程。