答案 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列表(我不知道还有什么要调用它),动态构建和执行,你应该做得很好。