使用动态sql创建一个包含sums的表

时间:2013-03-28 15:36:48

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

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

表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并使用WITH by with 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

2 个答案:

答案 0 :(得分:1)

我认为您需要进行动态调整,因为您的列名称未知且其数量也未知。我在下面的代码中做了类似的事情。 COALESCE是最神奇的,因为它构建了可以转向的列表。在我的例子中,“SysCode”将是“期间”列的等效物。

--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)

答案 1 :(得分:1)

由于您使用的是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)