【问题标题】:Joining many tables on same data and returning all rows在相同数据上连接多个表并返回所有行
【发布时间】:2012-11-22 13:10:04
【问题描述】:

更新:

我最初使用 FULL OUTER JOIN 的尝试没有正常工作。我已经更新了问题以反映真正的问题。很抱歉呈现经典XY PROBLEM。


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

最终的结果应该是这样的:

|年份 |月 | Col1 | Col2 | Col3 | |------+-------+------+------+------| | 2012 | 11 | 231 | - | - | | 2012 | 12 |第534章12 | 13 | | 2013 | 1 | - | 22 | 14 |

来自如下所示的数据:

表 1:

|年份 |月 |数据 | |------+--------+------| | 2012 | 11 | 231 | | 2012 | 12 |第534章

表 2:

|年份 |月 |数据 | |------+--------+------| | 2012 | 12 | 12 | | 2013 | 1 | 22 |

表 3:

|年份 |月 |数据 | |------+--------+------| | 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

结果是这样的(太混乱了,无法准确重复我使用此演示数据会得到的结果):

|年份 |月 | Col1 | Col2 | Col3 | |------+-------+------+------+------| | 2012 | 11 | 231 | - | - | | 2012 | 12 |第534章12 | 13 | | 2013 | 1 | - | 22 | | | - | 1 | - | - | 14 |

【问题讨论】:

  • 这个问题的标题真的很难用文字表达。如果您能想到更好的请编辑!
  • 刚刚意识到 FULL OUTER JOIN 甚至不适用于我想做的事情。例如,如果我选择在 t1.year 和 t1.month 加入每个表,那么如果 t2 和 t3 共享 t1 中不存在的日期,那么它不会正确加入
  • 顺便说一句,这个问题现在真的可以用一个更好的名字......有什么建议吗?

标签: tsql join


【解决方案1】:

如果您的数据允许(不是 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

【讨论】:

  • 这似乎有效。仍然有点乱,有很多列。这是最好的方法吗?
  • @NSjonas 如果您要经常使用它,可能值得创建一个视图。或者,请参阅我的其他帖子。
【解决方案2】:

如果您使用的是 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 测试和播放此查询。

【讨论】:

  • 不错!迄今为止最光滑的海事组织。对这个问题的标题有什么建议吗?
  • 说实话,想法不多。也许类似于“在同一行加入不同表的数据”?
【解决方案3】:

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

SELECT COALESCE(t1.data, t2.data)

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

【讨论】:

  • 很好,适用于空值,但我刚刚意识到完全外连接语句也不起作用......例如,如果我总是加入 t1 和 t2 和 t3 共享行在 t3 中不存在,则它们无法正确加入
  • 你能用一个加入 t3 的例子来更新这个问题,这样我们就可以看到你是怎么做的?
  • 完成,JBrooks 的答案有效,我暂时将其打开,因为我仍然认为它们可能是一个更优雅的解决方案
【解决方案4】:

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

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的现场演示。

【讨论】:

    【解决方案5】:

    如果您要从任一 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;
    

    【讨论】:

    • 这将简单地删除 t1 没有值的行。相反,如果 t1 没有该日期的值,但 t2 有,它应该从 t2 中选择月份和年份
    • 所以,您想在任一表具有“非空”值时显示数据.....您可以将“OR”运算符添加到表 2 的条件中。跨度>
    • 我不认为你明白...我需要模仿这个 CASE 语句 [SELECT CASE WHEN t1.year is null t2.year else t1.year END ...] 我是什么我问的是是否有办法加入这些表,所以我不必在我的 SELECT 子句中编写大量 CASE 语句
    【解决方案6】:

    这可能是一种更好的方法,尤其是如果您要在返回数据之前对其进行处理。基本上,您正在将数据来自的表转换为 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
    

    【讨论】:

      猜你喜欢
      • 2015-08-19
      • 2014-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-12
      • 2011-09-30
      相关资源
      最近更新 更多