在SQL Server中使用动态列进行透视

时间:2011-10-19 13:26:19

标签: sql-server-2005 tsql sql-server-2008 pivot dynamic-data

2 个答案:

答案 0 :(得分:11)

添加这些列非常简单。最后的查询将是

SELECT Account, AccountName, [Feb-11],[Jan-11],[Mar-11]   FROM   
(SELECT
t1.Col_Name,
t2.Account,
t2.AccountName,
t2.Amount
FROM Table1 AS t1
JOIN Table2 AS t2 ON t1.Col_ID1 = t2.Col_ID2
) p
PIVOT
(
Sum ([Amount] )
FOR Col_Name IN
( [Feb-11],[Jan-11],[Mar-11] )
) AS pvt 

将t2.AccountName添加到子查询中,并将Account和AccountName添加到初始SELECT中。把它们扔进构建语句中就完成了:

DECLARE @query NVARCHAR(4000)
SET @query = N'SELECT Account, AccountName, ' +    @cols +'   FROM   

(SELECT
t1.Col_Name,
t2.Account,
t2.AccountName,
t2.Amount
FROM Table1 AS t1
JOIN Table2 AS t2 ON t1.Col_ID1 = t2.Col_ID2
) p

PIVOT
(
Sum ([Amount] )
FOR Col_Name IN
( '+
@cols +' )
) AS pvt ' 

对于SQL注入,我能看到发生这种情况的唯一方法是,如果有人以某种方式在Table1.Col_Name中嵌入恶意代码,如果你不得不担心,那么你就会遇到比“锁定”这个动态查询更大的问题。

另外值得一提的是,我将使用以下内容来构建列列表(@Cols),因为它更短更容易阅读,但主要是因为我不喜欢XML。

DECLARE @cols NVARCHAR(2000)    
SELECT @cols = isnull(@cols + ',', '') + '[' + Col_Name + ']'
 FROM Table1
 ORDER BY Col_Name

答案 1 :(得分:1)

添加另一个答案,因为编辑几乎是第二个问题。 (没有细节和细节,我只能提供一般的大纲和伪代码 - 我不知道SAP。)

让我们从枢轴开始吧。它需要生成标记为,大概是月份的列,您在示例中将其作为Table1.Col_Name,varchar(10);提取这些值并将其作为列名称动态添加到数据透视查询中。如果数据库中没有此类列,则必须根据用户输入的数据为查询构造它。我将使用以下假设:   - 数据具有日期时间列,其中可以找到任何值(年到毫秒)   - 用户指定“开始日期”(它是否始终是一个月的第一天?),您必须为该日期和接下来的11个月生成列,汇总每个目标月份内的数据。

步骤1,我设置并填充包含12个目标列的临时表:

CREATE TABLE #Months
 (
   Col_Name    varchar(10)
  ,MonthStart  datetime
  ,MonthEnd    datetime
)

标签按您希望的格式显示,MonthStart将是月份的绝对开始(例如,2011年10月1日00:00:00.000),而MonthEnd将是下个月的绝对开始(11月1日) ,2011 00:00:00.000) - 这允许您使用SELECT … from <table> where DataDate >= MontStart and DataDate < MonthEnd获取该月内的所有数据。

接下来,将此表连接到数据表并进行汇总,例如:

SELECT
   mt.Col_Name
  ,sum(dt.RawData)  Amount
 from #Months mt
  inner join MyData dt
   on dt.DataDate >= mt.MonthStart
    and dt.DataDate < mt.MonthEnd  --  Yes, ON clauses don't have to be simple equivalencies!
  inner join <other tables as necessary for Account, AccountName, etc.>

将其作为pivot语句的最内层查询插入,使用非XML查询从临时表中提取/构建Col_Names列表(我不知道还有什么要调用它),动态构建和执行,你应该做得很好。