【问题标题】:How to get monthly data from three separate table如何从三个单独的表中获取月度数据
【发布时间】:2014-04-30 17:39:43
【问题描述】:

我有三个单独的表来存储数据。

Table1(每周执行和存储。使用上周的数据(例如 4/27 到 5/3))

Date         Value1     Value2
5/3/2014      56          13
5/10/2014     12          25
5/17/2014     90          52
5/24/2014     82          36
5/31/2014     76          98
6/7/2014      34          25
6/14/2014     13          63
6/21/2014     45          98
...

Table2(每周执行和存储。使用上周的数据(例如 4/27 到 5/3))

Date         Value3      Value4
5/3/2014       54          62
5/10/2014      43          36
5/17/2014      90          43
5/24/2014      54          35
5/31/2014      76          45
6/7/2014       34          43
6/14/2014      23          37
6/21/2014      34          56
...

Table3(从 4 月 27 日起每天执行和存储等)

Date         Value5      Value6
4/27/2014      56          45
4/28/2014      34          34
4/29/2014      23          34
4/30/2014      15          90
5/1/2014       34          23
5/2/2014       45          12
5/3/2014       46          35
5/4/2014       67          38
5/5/2014       34          23
...

如何编写一个按月计算每一列的查询?

我的桌子看起来像这样:

Month     Value1     Value2     Value3     Value4     Value5     Value6
April      NULL       NULL       NULL       NULL       128         203
May        316        224        317        221        226         131

我有查询获取当前月份的第一天:

CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, @DATE) as DATE)

下个月的第一天:

CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, DATEADD(m, 1, @DATE)) as DATE)

我认为我的查询可能是这样的:

SELECT
     DATENAME(MONTH, @DATE) as [Date],
     (SELECT [Value1] From [database].[dbo].[Table1]
          WHERE [Date] >= CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, @DATE) as DATE)
          AND [Date] < CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, DATEADD(m, 1, @DATE)) as DATE)
     ) AS [VAL1],
     (SELECT [Value2] From [database].[dbo].[Table1]
          WHERE [Date] >= CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, @DATE) as DATE)
          AND [Date] < CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, DATEADD(m, 1, @DATE)) as DATE)
     ) AS [VAL2],
     (SELECT [Value3] From [database].[dbo].[Table2]
          WHERE [Date] >= CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, @DATE) as DATE)
          AND [Date] < CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, DATEADD(m, 1, @DATE)) as DATE)
     ) AS [VAL3],
     (SELECT [Value4] From [database].[dbo].[Table2]
          WHERE [Date] >= CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, @DATE) as DATE)
          AND [Date] < CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, DATEADD(m, 1, @DATE)) as DATE)
     ) AS [VAL4],
     HOW TO DO VALUE5,
     HOW TO DO VALUE6
     INTO [database].[dbo].[tablemonthly]

我请求一些帮助以完成上述查询。

另外,我如何在上面的查询中使用IIF 语句,这样它只添加一次行并且只更新 Value5 和 Value6,因为它是 DAILY 并保持另一个完整,因为它将是更大的存储过程的一部分每天运行哪个?

我的三张桌子是:

【问题讨论】:

    标签: sql sql-server date


    【解决方案1】:

    为了确保您获得所需的所有月份,需要有一个参考表——这里我使用 CTE,但您可以只制作表。您还可以使用递归 CTE 根据输入构建表格,而不是像我在这里所做的那样对值进行硬编码。

    请注意,我正在使用 Gordon 提到的技术将所有数据连接到一个联合中。

    WITH Ranges AS
    (
       SELECT 'April' AS M, '4/1/2014' AS [START], '4/30/2014' AS [END]
      UNION ALL
       SELECT 'May', '5/1/2014', '5/31/2014'
    -- etc
    ), Data AS
    (
       select [date], value1, value2, NULL as value3, NULL as value4, NULL as value5, NULL as value6 from table1
     union all
       select [date], NULL, NULL, value3, value4, NULL, NULL from table2
     union all
       select [date], NULL, NULL, NULL, NULL, value5, value6 from table3
    )
    , Joined AS
    (
       SELECT M as [Month], Value1, Value2, Value3, Value4, Value5, Value6
       FROM Ranges R
       JOIN Data D ON D.[DATE] >= R.[START] AND D.[Date] <= R.[END]
    )
    SELECT [Month], SUM(Value1), SUM(Value2), SUM(Value3), SUM(Value4), SUM(Value5), SUM(Value6)
    FROM Joined
    GROUP BY [Month]
    

    【讨论】:

    • 这是否考虑到,Value5 和 Value6 是每天并基于月份添加的?
    • @SearchForKnowledge - 我想是的。
    • 5 月我的 VALUE1 列加起来为 170,但在我运行查询后,它给了我 3400,而 5 月的所有其他值也是错误的。
    • 那只给我一个月而已。
    • 我将用我创建的表格更新我的问题,以便您有更好的主意:)
    【解决方案2】:

    我认为最简单的方法是将表格合并在一起,然后提取您想要的内容:

    select datename(month, @date) as [date],
           max(value1) as value1, max(value2) as value2,
           max(value3) as value3, max(value4) as value4,
           sum(value5) as value5, sum(value6) as value6
    into [database].[dbo].[tablemonthly]
    from ((select [date], value1, value2, NULL as value3, NULL as value4, NULL as value5, NULL as value6
           from table1
          ) union all
          (select [date], NULL, NULL, value3, value4, NULL, NULL
           from table2
          ) union all
          (select [date], NULL, NULL, NULL, NULL, value5, value6
           from table3
          )
         ) t
    where [Date] >= CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, @DATE) as DATE) and
          [Date] < CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, DATEADD(m, 1, @DATE)) as DATE);
    

    您可以使用group by同时进行多个月。

    编辑:

    获取多个月份的查询是:

    select year([date]) as yr, month([date]) as mon,
           max(value1) as value1, max(value2) as value2,
           max(value3) as value3, max(value4) as value4,
           sum(value5) as value5, sum(value6) as value6
    into [database].[dbo].[tablemonthly]
    from ((select [date], value1, value2, NULL as value3, NULL as value4, NULL as value5, NULL as value6
           from table1
          ) union all
          (select [date], NULL, NULL, value3, value4, NULL, NULL
           from table2
          ) union all
          (select [date], NULL, NULL, NULL, NULL, value5, value6
           from table3
          )
         ) t
    group by year([date]), month([date])
    

    (为了避免歧义,我还输入了年份。)

    这会将where 替换为group by,并对select 进行相关更改。

    【讨论】:

    • 这是否考虑到 Value5 和 Value6 是每天并基于月份添加的?
    • @SearchForKnowledge 。 . .我想是的,现在我改用sum() 代替max() 来表示这些值。 where 应该确定正确的范围,sum() 应该将它们加在一起。
    • [strike]运行查询时出现Incorrect Syntax near ')' 错误[/strike] 我修复了查询。
    • 效果很好,除了该表还包含 5 月和 6 月的数据,此处未显示...
    • 那里出了点问题...对于 Value1 -> Value4 它只显示最后一个条目,而对于 Value5 和 Value6 它正确地进行计算...
    【解决方案3】:
    with MonthDataSummed(theMonth,value1,value2,value3,value4,value5,value6) as 
    (
        select dateName(Month,date),Sum(value1),Sum(value2),null,null,null,null from table11
         group by dateName(Month,date)
         UNION all
         select dateName(Month,date),NULL,NULL,Sum(value3),Sum(value4),null,null 
         from table22
         group by dateName(Month,date)
         UNION all
         select dateName(Month,date),NULL,NULL,NULL,NULL,Sum(value5),Sum(value6) 
         from table33
         group by dateName(Month,date)
     )
    ,SummedFlattened(theMonth,value1,value2,value3,value4,value5,value6) as 
    (
        select
        theMonth,Max(value1),Max(value2),Max(value3),Max(value4),Max(value5),Max(value6)
        from MonthDataSummed
        group by theMonth
    )
    SELECT * FROM SummedFlattened
    

    【讨论】:

    • 它没有正确添加它...只获取最后一个条目并在决赛桌中显示。不添加每次出现。
    • 哪个值是错误的?我使用了自己的测试数据。
    • 我想我能够做出一些改变并且可能已经让它发挥作用了 :)
    • 好的,但是当您对您的数据运行我的查询时,哪个结果值不正确?
    • 好的,我想我明白了。应该是 dateName(Month,date) 而不是 group by 中的 date。同意吗?
    【解决方案4】:

    此查询列出 VALUE#s 的 YEAR、MONTH 和总计。

    即使查询可能很长,它也会运行得非常快,因为连接在 Table1、Table2 和 Table3 的较小子集上运行(因为它们首先被过滤)。然后,使用 Date 列的 Month 和 Year 部分将它们连接起来。最后,数据按月和年排序。

    SELECT
    COALESCE(DATENAME(YEAR, Table1.[Date]), DATENAME(YEAR, Table2.[Date]), DATENAME(YEAR, Table3.[Date])) AS Year
    , COALESCE(DATENAME(MONTH, Table1.[Date]), DATENAME(MONTH, Table2.[Date]), DATENAME(MONTH, Table3.[Date])) AS Month 
    , COALESCE(SUM(Table1.Value1), 0) Value1 
    , COALESCE(SUM(Table1.Value2), 0) Value2 
    , COALESCE(SUM(Table2.Value3), 0) Value3 
    , COALESCE(SUM(Table2.Value4), 0) Value4 
    , COALESCE(SUM(Table3.Value5), 0) Value5 
    , COALESCE(SUM(Table3.Value6), 0) Value6 
    FROM
    (
      SELECT *
    FROM Table1
    WHERE [Date] >= CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, @DATE) as DATE)
    AND [Date] < CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, DATEADD(m, 9, @DATE)) as DATE)
    ) Table1
    FULL JOIN
    (
      SELECT *
    FROM Table2
    WHERE [Date] >= CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, @DATE) as DATE)
    AND [Date] < CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, DATEADD(m, 9, @DATE)) as DATE)
    ) Table2
    ON DATENAME(MONTH, Table1.[Date]) = DATENAME(MONTH, Table2.[Date])
    AND DATENAME(YEAR, Table1.[Date]) = DATENAME(YEAR, Table2.[Date])
    FULL JOIN
    (
      SELECT *
    FROM Table3
    WHERE [Date] >= CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, @DATE) as DATE)
    AND [Date] < CAST(DATEADD(d, - DATEPART(d, @DATE) + 1, DATEADD(m, 9, @DATE)) as DATE)
    ) Table3
    ON DATENAME(MONTH, Table1.[Date]) = DATENAME(MONTH, Table3.[Date])
    AND DATENAME(YEAR, Table1.[Date]) = DATENAME(YEAR, Table3.[Date])
    GROUP BY 
    COALESCE(DATENAME(YEAR, Table1.[Date]), DATENAME(YEAR, Table2.[Date]), DATENAME(YEAR, Table3.[Date]))
    , COALESCE(DATENAME(MONTH, Table1.[Date]), DATENAME(MONTH, Table2.[Date]), DATENAME(MONTH, Table3.[Date]))
    ORDER BY 
    COALESCE(DATENAME(YEAR, Table1.[Date]), DATENAME(YEAR, Table2.[Date]), DATENAME(YEAR, Table3.[Date]))
    , MONTH(CAST(COALESCE(DATENAME(MONTH, Table1.[Date]), DATENAME(MONTH, Table2.[Date]), DATENAME(MONTH, Table3.[Date])) + ' 1 2014' AS DATETIME));
    

    这是更新后的 SQL Fiddle demo,其中包含各种组合的数据。

    【讨论】:

    • 如果有一个月不在 Table1 中怎么办 - 这将失败。
    • @Hogan 同意。我将重新编写查询。
    • 查询是否重写以便我可以测试?谢谢:)
    • 谢谢。不催你,只是好奇,所以我可以测试一下:)
    • @SearchForKnowledge 我已经重写了查询。有机会时请测试一下:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-11
    • 2020-07-24
    • 2011-03-08
    • 2020-09-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多