具有不同列的表的UNION,但未指定它们,或者合并为FULL OUTER JOIN

时间:2015-02-03 20:44:12

标签: sql sql-server join union

我有一组表有很多不同的列(比如在SELECT子句中手动列出它们会是一件坏事。)

我想将它们组合在一起类似于UNION结果,除了UNION要求所有表中的列完全匹配(如果它们不是,则必须添加虚拟NULL值)。

所以:

Table1
Domain   | Field1 | Field2 | etc
foo.com    1        2        
bar.com    0        1        

Table2
Domain   | FieldX | FieldY | etc
foo.com     3        9        
baz.com    10       11        

Table3
Domain   | FieldA | FieldB | etc
baz.com    1        2        
qux.com    123      56        

期望的结果:

Domain | Field1 | Field2 | ... | FieldX | FieldY | ... | FieldA | FieldB | ...
foo.com  1        2               3        9
bar.com  0        1
baz.com                          10       11               1       2
qux.com                                                  123      56

我尝试使用FULL OUTER JOIN作为替代方案,但由于它是一个OUTER连接,它为我提供了过多的数据。

这是一个SQLFiddle:http://sqlfiddle.com/#!6/3fa84/2

2 个答案:

答案 0 :(得分:1)

首先使用UNION(不是UNION ALL)制作所有不同域名的列表(此处假设每个表中的域名都是唯一的)然后LEFT JOIN所有你的桌子。

DECLARE @Table1 TABLE ( [Domain] varchar(50), X1 int, X2 int );
DECLARE @Table2 TABLE ( [Domain] varchar(50), Y1 int, Y2 int );
DECLARE @Table3 TABLE ( [Domain] varchar(50), Z1 int, Z2 int );

INSERT INTO @Table1 ( [Domain], X1, X2 ) VALUES
( 'Foo.com', 1, 2 ),
( 'Bar.com', 0, 1 );

INSERT INTO @Table2 ( [Domain], Y1, Y2 ) VALUES
( 'Blah.com', 3, 0 ),
( 'Bar.com', 2, 1 ),
( 'reddit.com', -1, -2 );

INSERT INTO @Table3 ( [Domain], Z1, Z2 ) VALUES
( 'Gggg.com', 22, 33 ),
( 'Foo.com', 22, 44 ),
( 'bar.com', 50, 51 ),
( 'reddit.com', 10, 20 );

WITH
CTE_Domains
AS
(
    SELECT Domain FROM @Table1
    UNION
    SELECT Domain FROM @Table2
    UNION
    SELECT Domain FROM @Table3
)
SELECT
    CTE_Domains.Domain
    ,X1
    ,X2
    ,Y1
    ,Y2
    ,Z1
    ,Z2
FROM
    CTE_Domains
    LEFT JOIN @Table1 AS T1 ON T1.Domain = CTE_Domains.Domain
    LEFT JOIN @Table2 AS T2 ON T2.Domain = CTE_Domains.Domain
    LEFT JOIN @Table3 AS T3 ON T3.Domain = CTE_Domains.Domain
ORDER BY CTE_Domains.Domain;

这是结果集:

Domain        X1      X2      Y1      Y2      Z1      Z2
Bar.com       0       1       2       1       50      51
Blah.com      NULL    NULL    3       0       NULL    NULL
Foo.com       1       2       NULL    NULL    22      44
Gggg.com      NULL    NULL    NULL    NULL    22      33
reddit.com    NULL    NULL    -1      -2      10      20

如果您编写SELECT *而不是显式列列表,则结果集将为此。每个连接表都会重复Domain列。

Domain        Domain     X1      X2      Domain        Y1      Y2      Domain        Z1      Z2
Bar.com       Bar.com    0       1       Bar.com       2       1       bar.com       50      51
Blah.com      NULL       NULL    NULL    Blah.com      3       0       NULL          NULL    NULL
Foo.com       Foo.com    1       2       NULL          NULL    NULL    Foo.com       22      44
Gggg.com      NULL       NULL    NULL    NULL          NULL    NULL    Gggg.com      22      33
reddit.com    NULL       NULL    NULL    reddit.com    -1      -2      reddit.com    10      20

答案 1 :(得分:0)

这样的东西可以给你你想要的没有多余的行:

SELECT COALESCE(t3.Domain, t1t2.Domain) AS Domain,    
       t1t2.X1, t1t2.X2, t1t2.Y1, t1t2.Y2,
       t3.Z1, t3.Z2
FROM Table3 AS t3
FULL OUTER JOIN (
   SELECT COALESCE(t1.Domain, t2.Domain) AS Domain, t1.X1, t1.X2, t2.Y1, t2.Y2
   FROM Table1 AS t1
   FULL OUTER JOIN Table2 AS t2 ON t1.Domain = t2.Domain ) AS t1t2
      ON t3.Domain = t1t2.Domain

SQL Fiddle Demo here