在相同数据上连接许多表并返回所有行

时间:2012-12-04 19:56:59

标签: tsql join

UPDATE:

我使用FULL OUTER JOIN的区域尝试无法正常工作。我已经更新了问题,以反映真正的问题。很抱歉出示经典XY PROBLEM


我正在尝试从一个查询中的多个表中检索数据集,这些数据按年份,数据分组。

最终结果应如下所示:

| Year | Month | Col1 | Col2 | Col3 |
|------+-------+------+------+------|
| 2012 |   11  |  231 |   -  |  -   |
| 2012 |   12  |  534 |  12  |  13  |
| 2013 |   1   |   -  |  22  |  14  |

来自这样的数据:

表1:

| Year | Month | Data |
|------+-------+------|
| 2012 |   11  |  231 |
| 2012 |   12  |  534 |

表2:

| Year | Month | Data |
|------+-------+------|
| 2012 |   12  |  12  |
| 2013 |   1   |  22  |

表3:

| Year | Month | Data |
|------+-------+------|
| 2012 |   12  |  13  |
| 2013 |   1   |  14  |

我尝试使用FULL OUTER JOIN,但这不是很有效,因为在我的SELECT子句中,因为无论哪个表我选择'年'和'月'都有空值。

SELECT 
 Collase(t1.year,t2.year,t3.year)
,Collese(t1.month,t2.month,t3.month)
,t1.data as col1
,t2.data as col2
,t3.data as col3
From t1
FULL OUTER JOIN t2
on t1.year = t2.year and t1.month = t2.month
FULL OUTER JOIN t3
on t1.year = t3.year and t1.month = t3.month

结果是这样的(太难以重复使用此演示数据完全得到的内容):

| Year | Month | Col1 | Col2 | Col3 |
|------+-------+------+------+------|
| 2012 |   11  |  231 |   -  |  -   |
| 2012 |   12  |  534 |  12  |  13  |
| 2013 |   1   |   -  |  22  |      |
|  -   |   1   |   -  |  -   |  14  |

6 个答案:

答案 0 :(得分:2)

如果您的数据允许(不是100列),这通常是一种干净的方式:

select year, month, sum(col1) as col1, sum(col2) as col2, sum(col3) as col3
from (
    SELECT t1.year, t1.month, t1.data as col1, 0 as col2, 0 as col3
    From t1
    union all 
    SELECT t2.year, t2.month, 0 as col1, t2.data as col2, 0 as col3
    From t2
    union all 
    SELECT t3.year, t3.month, 0 as col1, 0 as col2, t3.data as col3
    From t3
) as data
group by year, month

答案 1 :(得分:1)

也许您正在寻找COALESCE关键字?它接受一列列并返回第一个NOT NULL,如果所有参数都为null,则返回NULL。在你的例子中,你会做这样的事情。

SELECT COALESCE(t1.data, t2.data)

在这种情况下,您仍然需要连接表。它只会减少案例陈述。

答案 2 :(得分:1)

您可以从所有表中派生完整的年份和月份列表,而不是将每个表连接到该列表(使用左连接):

SELECT 
  f.Year,
  f.Month,
  t1.data AS col1,
  t2.data AS col2,
  t3.data AS col3
FROM (
  SELECT Year, Month FROM t1
  UNION
  SELECT Year, Month FROM t2
  UNION
  SELECT Year, Month FROM t3
) f
LEFT JOIN t1 ON f.year = t1.year and f.month = t1.month
LEFT JOIN t2 ON f.year = t2.year and f.month = t2.month
LEFT JOIN t3 ON f.year = t3.year and f.month = t3.month
;

您可以看到此查询的实时演示at SQL Fiddle

答案 3 :(得分:1)

如果您使用的是SQL Server 2005或更高版本,您也可以尝试使用此PIVOT解决方案:

SELECT 
  Year,
  Month,
  Col1,
  Col2,
  Col3
FROM (
  SELECT Year, Month, 'Col1' AS Col, Data FROM t1
  UNION ALL
  SELECT Year, Month, 'Col2' AS Col, Data FROM t2
  UNION ALL
  SELECT Year, Month, 'Col3' AS Col, Data FROM t3
) f
PIVOT (
  SUM(Data) FOR Col IN (Col1, Col2, Col3)
) p
;

可以使用at SQL Fiddle测试和播放此查询。

答案 4 :(得分:0)

如果您要从tabloe中查找非空值,则还必须添加t1.dat IS NOT NULL。我希望我理解你的问题。

CREATE VIEW joined_SALES
AS SELECT t1.year, t1.month, t1.data , t2.data 
FROM table1 t1, table2 t2
WHERE
    t1.year = t2.year 
    and    t1.month = t2.month
    and    t1.dat IS NOT NULL
GROUP BY t1.year, t1.month;

答案 5 :(得分:0)

这可能是一种更好的方法,特别是如果您要在返回数据之前对数据执行某些操作。基本上,您正在将数据来自的表转换为typeId。

declare @temp table 
([year] int,
[month] int,
typeId int,
data decimal)


insert into @temp
SELECT t1.year, t1.month, 1,  sum(t1.data)
From t1
group by t1.year, t1.month

insert into @temp
SELECT t2.year, t2.month, 2,  sum(t2.data)
From t2
group by t1.year, t1.month


insert into @temp
SELECT t3.year, t3.month, 3,  sum(t3.data)
group by t1.year, t1.month


select t.year, t.month, 
sum(case when t.typeId = 1 then t.data end) as col1, 
sum(case when t.typeId = 2 then t.data end) as col2, 
sum(case when t.typeId = 3 then t.data end) as col3 
from @temp t
group by t.year, t.month