如何在SQL中实现PIVOT?

时间:2018-11-01 14:23:37

标签: sql-server

我有一个表 Transaction_Info ,该表包含以下几列: Customer_Id 销售总额交易日期

我想在运输批准日期上为销售总额设置SQL Pivot。

我编写了以下SQL查询:

DECLARE   @SQLQuery AS NVARCHAR(MAX)
DECLARE   @PivotColumns AS NVARCHAR(MAX)

SELECT @PivotColumns = STUFF( (SELECT DISTINCT ', '+ QUOTENAME(CAST(YEAR(TRANSACTION_DATE) AS VARCHAR(255)))
                       FROM TRANSACTION_INFO
                       FOR XML PATH('')
                      ), 1, 1, ''
                    )

SET @SQLQuery = 
N'SELECT CUSTOMER_ID, '+ @PivotColumns + '
FROM TRANSACTION_INFO
PIVOT(SUM(TOTAL_AMT) FOR YEAR(TRANSACTION_DATE) IN (' +@PivotColumns+')) AS P'

以下结果是预期的输出。

SELECT @PivotColumns

--OUTPUT

[2013], [2011], [2012], [2014]


SELECT @SQLQuery

-- OUTPUT

SELECT CUSTOMER_ID,  [2013], [2011], [2012], [2014]FROM TRANSACTION_INFOPIVOT(SUM(TOTAL_AMT) FOR YEAR(TRANSACTION_DATE) IN ( [2013], [2011], [2012], [2014])) AS P

但是以下内容返回错误'('

附近的语法不正确
EXEC sp_executesql @SQLQuery

我无法找出错误。在这方面的任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:0)

我想你只是想要一个分组对象

SELECT customer_id, year(transaction_date) as year, sum(total_sales) as total
FROM transaction_info
GROUP BY customer_id, year(transaction_date)

答案 1 :(得分:0)

您不需要在SQL需要列名的地方应用任意表达式。使用子查询首先提取年份值并以此为基础:

N'SELECT CUSTOMER_ID, '+ @PivotColumns + '
FROM (SELECT
         CUSTOMER_ID,
         TOTAL_AMT,
         YEAR(TRANSACTION_DATE) as TRANSACTION_YEAR
      FROM TRANSACTION_INFO) TI
PIVOT(SUM(TOTAL_AMT) FOR TRANSACTION_YEAR IN (' +@PivotColumns+')) AS P'

请注意Syntax 1

PIVOT  
(  
    <aggregation function>(<column being aggregated>)  
FOR   
[<column that contains the values that will become column headers>]   
    IN ( [first pivoted column], [second pivoted column],  
    ... [last pivoted column])  
) AS <alias for the pivot table>

所有这些占位符都要求column就是这个意思。您不能在此处使用表达式。另外请注意,例如,这意味着您无法在聚合内执行任何类型的复杂计算。


1 但是请注意,这里有一个文档错误。 <column that contains the values that will become column headers>不是可选的。

答案 2 :(得分:-1)

要进行PIVOT-您需要在“ @PivotColumns”列表中使用方括号。 我觉得我需要提供一个简单的示例,设置列表格式-由您决定。 在示例中用作参数的全局虚拟表不能在“文本”中使用:

begin try
    drop table #pvt
end try
begin catch
end catch

create table #pvt(VendorID int, Emp1 int, Emp2 int,
    Emp3 int, Emp4 int, Emp5 int)

INSERT INTO #pvt VALUES (1,4,3,5,4,4)
INSERT INTO #pvt VALUES (2,4,1,5,5,5)
INSERT INTO #pvt VALUES (3,4,3,5,4,4)
INSERT INTO #pvt VALUES (4,4,2,5,5,4)
INSERT INTO #pvt VALUES (5,5,1,5,5,5)

select * from #pvt 
------------------------------------
--Unpivot the table.
SELECT VendorID, Employee, Orders
FROM 
   (SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
   FROM #pvt) p
UNPIVOT
   (Orders FOR Employee IN 
      (Emp1, Emp2, Emp3, Emp4, Emp5)
)AS unpvt
----------------------------------------
select pv.* 
from(
--Unpivot the table.
SELECT VendorID, Employee, Orders
FROM 
   (SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
   FROM #pvt) p
UNPIVOT
   (Orders FOR Employee IN 
      (Emp1, Emp2, Emp3, Emp4, Emp5)
)AS unpvt
) t
pivot (sum(Orders) for Employee in([Emp1],[Emp2],[Emp3],[Emp4],[Emp5])) pv

declare @sql varchar(max)
set @sql='select pv.* 
from(
--Unpivot the table.
SELECT VendorID, Employee, Orders
FROM 
   (SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
   FROM #pvt) p
UNPIVOT
   (Orders FOR Employee IN 
      (Emp1, Emp2, Emp3, Emp4, Emp5)
)AS unpvt
) t
pivot (sum(Orders) for Employee in([Emp1],[Emp2],[Emp3],[Emp4],[Emp5])) pv'
exec(@sql)