【问题标题】:Create a table with sums using dynamic sql使用动态 sql 创建一个包含总和的表
【发布时间】:2013-07-02 10:28:47
【问题描述】:

我需要动态选择的值是日期,因此会发生变化(即每周或每月)。我想知道如何使用 TSQL (SQL Server 2008) 中的“EXEC”函数来做到这一点

Table Regis 有 4 列,数据类似这样(有 90k 行):

Holder     Period       State  Ttl
Dell       2011-12-31   CA     5
Dell       2012-01-31   PA     7
Sony       2011-11-30   TX     8
Sony       2013-02-28   FL     20

总计是该州在该日期结束的月份的总“销售额”。该销售数据跨越 14 个月。但是,它可能会增长到 20 个月。此外,日期会随着时间的推移而改变,因为它是滚动月份。我只想获得州总交易,以“期间”为列。

我知道删除 Holder 并将 Group by 与 SUM 一起使用,将横向执行此操作。我也知道,通过了解所有时期,我可以使用枢轴。但是,我希望将 Period 作为列,并希望通过动态 SQL 来做到这一点,因为我需要学习动态 SQL 来做其他事情。感谢您的帮助。

最终结果应该是这样的

state    2011-11-30  2011-12-31... 2013-02-28
CA       100         205           78
WA       90          159           62
CO       16          654           31
TX       87          321           205
NY       54          45            415

【问题讨论】:

    标签: tsql sql-server-2008-r2 dynamic-sql


    【解决方案1】:

    我认为您需要进行动态数据透视,因为您的列名是未知的,而且它们的数量也是未知的。我在下面的代码中做了类似的事情。 COALESCE 是最神奇的,因为它构建了要根据的列表。在我的示例中,“SysCode”将等同于您的“Period”列。

    --Pull the data set
    
    DECLARE
        @Query NVARCHAR(4000)
    
    INSERT INTO 
        #Rates
    
    SELECT 
        CAST(mrc.StartDay AS DATE) [Start Date],
        CAST(mrc.EndDay AS DATE) [End Date],
        dpe.NCCDayPart [Daypart],
        dpe.NCCDayPartDescription [Description],
        mrc.Network,
        ru.SysCode,
        mrc.Rate
    
    FROM 
        minimumratecards mrc
        LEFT JOIN DaypartExtension dpe
            ON mrc.DayPartSequence = dpe.Sequence
            AND dpe.Division = 'CAMC'
        LEFT JOIN #RetailUnit ru
            ON mrc.RetailUnitCode = ru.RetailUnit
    
    
    WHERE
        mrc.MinimumRateCardID = @MinimumRateCardID
    
    
    
    --Get a distinct list of syscodes that were returned    
    SELECT DISTINCT
        Syscode
    
    INTO
        #Syscodes
    
    FROM
        #Rates
    
    
    
    --Format the syscode list into a string to be used in the pivot table
    SELECT 
        @Cols = COALESCE(@Cols + ',[' + SysCode + ']',
                             '[' + SysCode + ']')
    FROM    
        #Syscodes
    
    ORDER BY 
        SysCode
    
    
    
    --Pivot the data
    SET @Query = 
        N'SELECT 
            [Start Date],
            [End Date],
            [Daypart],
            [Description],
            [Network], '+
            @Cols +'
        FROM
        (SELECT 
            [Start Date],
            [End Date],
            [Daypart],
            [Description],
            [Network],
            [Rate],
            [SysCode]
        FROM    #Rates AS t1) p
        PIVOT
            (
            MAX([Rate])
            FOR [SysCode] IN
            ( '+
            @Cols +' )
            ) AS pvt
            ORDER BY [Network];'
    
    
    EXECUTE(@Query)
    

    【讨论】:

      【解决方案2】:

      由于您使用的是 SQL Server,因此您可以使用 PIVOT 函数将行转换为列。

      在进入动态版本之前,更容易了解代码是如何设置为有限值或静态值的。对于您的数据,您将使用:

      select *
      from
      (
        select period, state, ttl
        from regis
      ) d
      pivot
      (
        sum(ttl)
        for period in ([2011-11-30], [2011-12-31], [2013-02-28])
      ) piv;
      

      SQL Fiddle with Demo

      您将需要创建将在数据透视表中使用的不同 period 值的列表。创建此列表的代码类似于:

      select @cols = STUFF((SELECT distinct ',' + QUOTENAME(Period) 
                          from regis
                  FOR XML PATH(''), TYPE
                  ).value('.', 'NVARCHAR(MAX)') 
              ,1,1,'')
      

      您将用于创建动态 SQL 的代码是:

      DECLARE @cols AS NVARCHAR(MAX),
          @query  AS NVARCHAR(MAX)
      
      select @cols = STUFF((SELECT distinct ',' + QUOTENAME(Period) 
                          from regis
                  FOR XML PATH(''), TYPE
                  ).value('.', 'NVARCHAR(MAX)') 
              ,1,1,'')
      
      set @query = 'SELECT state, ' + @cols + ' from 
                   (
                      select period, state, ttl
                      from regis
                  ) x
                  pivot 
                  (
                      sum(ttl)
                      for period in (' + @cols + ')
                  ) p '
      
      execute(@query)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-07
        • 2021-06-21
        • 2017-01-08
        • 2021-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多