使用 VARCHAR 列旋转 SQL 服务器 table 时出现语法错误

Syntax error in pivoting a SQL Server table using VARCHAR columns

我在 SQL 服务器中有一个 table(~50m 行)如下所示:

PId        CustomColumnName        CustomColumnValue
1          PropertyA               1
1          PropertyB               B
1          PropertyC               C
2          PropertyA               1.5
2          PropertyB               BB
2          PropertyC               CC
3          PropertyD               D1
3          PropertyA               2.0

我想 PIVOT table 看起来像这样:

PId    PropertyA    PropertyB    PropertyC    PropertyD
1      1            B            C            NULL
2      1.5          BB           CC           NULL
3      2.0          NULL         NULL         D1

我知道SQL服务器有PIVOT功能,所以我写了这样的东西:

  SELECT *
  FROM 
  ( 
  SELECT [PId], [CustomColumnName], [CustomColumnValue] 
  FROM [myTable]
  ) AS src
  PIVOT
  (
  MAX([CustomColumnValue]) -- Not sure how to aggregate VARCHAR data here
  FOR [CustomColumnName] IN ('PropertyA', 'PropertyB', 'PropertyC', 'PropertyD')
  ) AS pvt

但是我遇到了 Incorrect syntax near 'PropertyA' 错误。我不确定 SQL 服务器的 PIVOT 功能是否可以实现我正在尝试做的事情(因为我认为我无法聚合 [CustomColumnValue],这是VARCHAR 类型)。 如果在我的用例中使用 PIVOT 不可行,是否有有效的替代方法来实现我正在尝试做的事情?

提前感谢您的 suggestions/answers!

--去掉单引号你会得到想要的结果集

;With cte(PId, CustomColumnName,CustomColumnValue)
    AS
    (
    SELECT 1,'PropertyA','1'    Union all
    SELECT 1,'PropertyB','B'    Union all
    SELECT 1,'PropertyC','C'    Union all
    SELECT 2,'PropertyA','1.5'  Union all
    SELECT 2,'PropertyB','BB'   Union all
    SELECT 2,'PropertyC','CC'   Union all
    SELECT 3,'PropertyD','D1'   Union all
    SELECT 3,'PropertyA','2.0'
    )
     SELECT *
      FROM 
      ( 
      SELECT [PId], [CustomColumnName], [CustomColumnValue] 
      FROM cte
      ) AS src
      PIVOT
      (
      MAX([CustomColumnValue]) 
      FOR [CustomColumnName] IN (PropertyA, PropertyB, PropertyC, PropertyD)
      ) AS pvt

您可以使用动态生成相同的结果集Pivot.it如下

IF OBJECT_ID('tempdb..#temp') IS NOT NULL
Drop table #temp
;With cte(PId, CustomColumnName,CustomColumnValue)
AS
(
SELECT 1,'PropertyA','1'    Union all
SELECT 1,'PropertyB','B'    Union all
SELECT 1,'PropertyC','C'    Union all
SELECT 2,'PropertyA','1.5'  Union all
SELECT 2,'PropertyB','BB'   Union all
SELECT 2,'PropertyC','CC'   Union all
SELECT 3,'PropertyD','D1'   Union all
SELECT 3,'PropertyA','2.0'
)
SELECT * INTO #temp FROM cte

Declare 
         @Sql nvarchar(max),
         @dynamicCol nvarchar(max)
--Create columns Dynamically
SELECT @dynamicCol=STUFF((SELECT DISTINCT ', '+ QUOTENAME(CustomColumnName )
From  #temp For XML PATH ('')),1,1,'')

--SELECT @dynamicCol

SET @Sql='
SELECT [PId] ,'+ @dynamicCol +' From
(
SELECT [PId], [CustomColumnName], [CustomColumnValue]  From
#temp
)AS Src
PIVOT 
(
MAX([CustomColumnValue]) For [CustomColumnName] IN ('+@dynamicCol+')
)
AS Pvt'

PRINT @Sql

EXEC(@Sql)

删除引号。

SELECT * 
  FROM 
  ( 
  SELECT [PId], [CustomColumnName], [CustomColumnValue] 
  FROM [myTable]
  ) AS src
  PIVOT
  (MAX([CustomColumnValue])
   FOR [CustomColumnName] IN ([PropertyA], [PropertyB], [PropertyC], [PropertyD])
  ) AS pvt
GO
PId | PropertyA | PropertyB | PropertyC | PropertyD
--: | :-------- | :-------- | :-------- | :--------
  1 | 1         | B         | C         | null     
  2 | 1.5       | BB        | CC        | null     
  3 | 2.0       | null      | null      | D1       

dbfiddle here

您需要使用列的引用名

SELECT *
  FROM 
  ( 
  SELECT [PId], [CustomColumnName], [CustomColumnValue] 
  FROM [myTable]
  ) AS src
  PIVOT
  (
  MAX([CustomColumnValue]) -- Not sure how to aggregate VARCHAR data here
  FOR [CustomColumnName] IN ([PropertyA], [PropertyB], [PropertyC], [PropertyD])  --provide in squarebrackets if generating dynamic then use quotename() function of sql server
  ) AS pvt