0

我需要动态选择的值是日期,因此会发生变化(即每周或每月)。我想知道如何使用 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 并将 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
4

2 回答 2

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)
于 2013-03-28T15:47:02.227 回答
1

Since you are using SQL Server you can use the PIVOT function to transform your rows into columns.

Before jumping into a dynamic version it is easier to see how the code is set up for limited or static values. For your data, you will use:

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;

See SQL Fiddle with Demo.

You will need to create a list of the distinct period values that will be used in the pivot. The code to create this list will be similar to :

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

The code that you will use to create the dynamic SQL is:

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)
于 2013-03-28T15:49:53.367 回答