【问题标题】:Return a column per date in a range返回范围内每个日期的列
【发布时间】:2017-02-13 18:44:35
【问题描述】:

我正在使用以下 SQL 查询:

select  brn,
        [time],
        sum(value) as [value]
from dbo.sales 
where date = '2014-12-31 00:00:00'     
    and brn = 1 
    and [time]!='ZZZZ'
group by brn, [time]
order by brn, [time]

我得到的结果是:

brn time    value
1   0800    0.00
1   0900    52.79
1   1000    5.73
1   1100    9.63
1   1200    200.08

现在我想要几个日期的结果(一年 - 从 31-12-2014 到 31-12-2015),

例如:

brn time    31/12/2014  01/01/2015  02/01/2015  03/01/2015
1   800     5.73        5.73        5.73        5.73
1   900     52.79       52.79       52.79       52.79
1   1000    5.73        5.73        5.73        5.73
1   1100    9.63        9.63        9.63        9.63
1   1200    200.08      200.08      200.08      200.08

【问题讨论】:

    标签: sql sql-server tsql pivot


    【解决方案1】:

    您可以使用带透视的动态 SQL:

    select  brn,
            [time],
            sum(value) as [value],
            [date]
    INTO #temp
    from dbo.sales 
    where brn = 1 and [time]!='ZZZZ'
         AND [date] between '2014-12-31' and '2015-12-31'
    group by brn, [time], [date]
    
    
    DECLARE @sql nvarchar(max),
            @col nvarchar(max)
    
    SELECT @col = (
        SELECT DISTINCT ','+QUOTENAME([date])
        FROM #temp
        FOR XML PATH ('')
    )
    
    SELECT @sql = N'
    SELECT *
    FROM #temp
    PIVOT (
        MAX([value]) FOR [date] IN ('+STUFF(@col,1,1,'')+')
    ) as pvt)'
    
    EXEC sp_executesql @sql
    

    【讨论】:

    • 谢谢。但我明白了 - 必须声明标量变量“@sql”。
    • 我在这里声明它DECLARE @sql nvarchar(max), 并且它正在工作。你也这样声明吗?
    • 我按照下面的程序,第 1 步 -> 打开了新查询 ->select brn, --- group by brn, [time], [date] -> 执行了查询。第 2 步-> 将DECLARE @sql nvarchar(max), @col nvarchar(max) SELECT @col = ( --- MAX([value]) FOR [date] IN ('+STUFF(@col,1,1,'')+') ) as pvt)' 复制到新查询中-> 执行。第 3 步 -> 使用 EXEC sp_executesql @sql。在执行第 3 步时,我收到此错误。这是正确的程序吗?
    • 所有这批必须一次执行:)
    • @AbdullahAlMamun 您只能在枢轴中的“值”上使用,如果您需要另一个值,您可以使用相同的脚本,然后加入到枢轴结果中。
    【解决方案2】:

    您可以使用条件聚合:

    select brn, [time],
           sum(case when date = '2014-12-31' then value else 0 end)) as value_20141231,
           sum(case when date = '2015-01-01' then value else 0 end)) as value_20150101,
           . . .
    from dbo.sales 
    where brn = 1  and 
         [time] <> 'ZZZZ'
    group by brn, [time]
    order by brn, [time];
    

    您还可以使用and date in ('2014-12-31', '2015-01-01', . . .) 限制where 中的日期。

    【讨论】:

      【解决方案3】:

      对于为日期构建的列名,您可以创建一个SQL dates table 然后使用动态 SQL,您可以将这些用作选择字段 也许您可以查看dynamic pivot sql query,了解如何将日期表中的字段值连接到数据透视查询字段中

      这是 SQL 脚本

      DECLARE @dates nvarchar(max)
      SELECT @dates =
       STUFF(
       (
          SELECT ', value as [' + convert(varchar(30), cast([date] as date), 112) + ']'
          FROM [dbo].[DateTable]('20150101', '20151231')
          for xml path('')
       ),
       1,1,'')
      
      DECLARE @SQL nvarchar(max)
      SELECT @SQL = N'select brn, time, value, ' + @dates + ' from mydata'
      exec sp_executesql @SQL 
      

      输出如下

      您可以格式化日期值的字符串表示形式,如SQL Format Date 文章中所示。 例如,您可以将 103 用于 dd/mm/yyyy,而不是参数 112

      希望对解决有帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-26
        • 1970-01-01
        相关资源
        最近更新 更多