尝试使用动态数据透视查询时出现语法错误

Syntax Error when trying to use Dynamic Pivot Query

我已经研究 PIVOT 函数一段时间了。我有一个 table 看起来像这样

IdPersona IdEstadoSocio Periodo
-------------------------------
1044659   6             2021-06
721396    5             2021-06
219886    6             2021-06
1906611   7             2021-06
1027906   2             2021-06

每个 ClientID 每个月重复一次。每个月都会将新行添加到 table 中,并与该行关联一个新的句点。这是递增的 table.

我需要做的是 PIVOT table,这样它基本上就这样结束了:

IdPersona 2021-01 2021-02 2021-03 2021-04 
----------------------------------------
1044659  6       3       1       4
721396   5       5       2       6 
219886   6       6       4       1
1906611  7       7       9       2 
1027906  2       1       1       1

当然,我希望我的代码是动态的。我不想每个月 harcode 像:

    SELECT *
FROM [fid].[FACT_Socios_Resumen_Periodo]
PIVOT(MAX(IdEstadoSocio) 
      FOR [Periodo] IN ([2021-01], [2021-02], [2021-03], [2021-04], [2021-05], [2021-06])) AS PVTTable

所以我一直在尝试在这里找到的几种动态解决方案,但其中 none 对我有用,我不知道为什么。这让我发疯。

This solutions 给我

Incorrect Syntax near 'FOR'

我的代码如下:

DECLARE @cols AS NVARCHAR(MAX),@query  AS NVARCHAR(MAX);

SET @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(periodo) 
            FROM [fid].[FACT_Socios_Resumen_Periodo]
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT IdPersona, ' + @cols + ' from 
            (
                select IdPersona
                    , IdEstadoSocio
                    , periodo
                from [fid].[FACT_Socios_Resumen_Periodo]
           ) x
            pivot 
            (
                 max(IdEstadoSocio)
                for periodo in (' + @cols + ')
            ) p '

execute(@query)

同link中提供的second solution给我

A variable that has been assigned in a SELECT statement cannot be included in a expression or assignment when used in conjunction with a from clause.

这是可以理解的,因为据我所知,查询试图以递归方式解决获取 [Period] 的 DISTINCT 值的问题。然而,每个人都接受了这个可行的答案。

我的代码如下:

DECLARE @cols  AS NVARCHAR(MAX)='';
DECLARE @query AS NVARCHAR(MAX)='';

SELECT @cols = @cols + QUOTENAME(periodo) + ',' FROM (select distinct periodo from [fid].[FACT_Socios_Resumen_Periodo] ) as tmp
select @cols = substring(@cols, 0, len(@cols)) --trim "," at end

set @query = 
'SELECT * from 
(
    select idpersona, idestadosocio, periodo from [fid].[FACT_Socios_Resumen_Periodo]
) src
pivot 
(
    max(idestadosocio) for periodo in (' + @cols + ')
) piv'

execute(@query)

我试过的 third solution 给了我上面提到的相同错误,语法相似但不完全相同。它尝试递归地解决 DISTINCT [Period]s。

我的代码如下:

DECLARE @DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE @ColumnName AS NVARCHAR(MAX)

--Get distinct values of the PIVOT Column 
SELECT @ColumnName = ISNULL(@ColumnName + ',', '') + QUOTENAME(periodo)
FROM (SELECT DISTINCT periodo FROM [fid].[FACT_Socios_Resumen_Periodo]) AS Periodos
 
--Prepare the PIVOT query using the dynamic 
SET @DynamicPivotQuery = 
  N'SELECT IdPersona, ' + @ColumnName + '
    FROM [fid].[FACT_Socios_Resumen_Periodo]
    PIVOT(MAX(IdEstadoSocio) 
          FOR periodo IN (' + @ColumnName + ')) AS PVTTable'
--Execute the Dynamic Pivot Query
EXEC sp_executesql @DynamicPivotQuery

所以,我到底做错了什么??有人可以给我提示吗?我正在对整个社区批准的解决方案进行故障处理,我不明白为什么。我基本上试图理解代码,复制它,并替换列和 tables。只是。我没有再改变任何东西。提前致谢!

查看您的第三个解决方案。

我注意到的第一件事是,您在进行串联时没有合并 @ColumnName 的初始空值。

SELECT @ColumnName = Isnull(@ColumnName + ',', '') + QUOTENAME(periodo)
FROM (SELECT DISTINCT periodo FROM [fid].[FACT_Socios_Resumen_Periodo]) AS Periodos

这应该可以解决您的问题。

如果您打印结果@ColumnName 和@DynamicPivotQuery,在执行之前,它通常会告诉您问题出在哪里。

对于不支持 SELECT @Variable

的 sql 版本

SQL Azure 和 SQL DW 仅支持在设置变量值时使用 SET。 您可以在这些服务器上使用 STRING_AGG()

set @ColumnName = (select string_agg(QUOTENAME(periodo),',') from (select distinct periodo from FACT_Socios_Resumen_Periodo) t)