尝试使用动态透视查询时出现语法错误
Posted
技术标签:
【中文标题】尝试使用动态透视查询时出现语法错误【英文标题】:Syntax Error when trying to use Dynamic Pivot Query 【发布时间】:2021-09-18 09:41:26 【问题描述】:我已经玩了一段时间的 PIVOT 功能。我有一张像这样的表
IdPersona IdEstadoSocio Periodo
-------------------------------
1044659 6 2021-06
721396 5 2021-06
219886 6 2021-06
1906611 7 2021-06
1027906 2 2021-06
每个 ClientID 每个月都会重复一次。每个月都会将新行添加到表中,并带有与该行关联的新期间。这是一个递增表。
我需要做的是 PIVOT 表,所以它基本上是这样结束的:
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
所以我一直在尝试在这里找到的几种动态解决方案,但没有一个对我有用,我不知道为什么。这让我发疯了。
This solutions给我
“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)
同一链接中提供的second solution 给了我
在 SELECT 语句中分配的变量不能 与 a 一起使用时包含在表达式或赋值中 from 子句。
这有点可以理解,因为据我了解,查询试图以递归方式解决获取 [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]。
我的代码如下:
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
那么,我到底做错了什么?有人可以给我一个提示吗?我失败了整个社区批准的解决方案,我不明白为什么。我基本上试图理解代码,复制它,并替换列和表。只是。我没有再做任何改变。提前致谢!
【问题讨论】:
完成!我的错。这么久第一次发帖,不好意思 我检查了您发布的三个代码段,没有错误。我认为你做得对。 【参考方案1】:查看您的第三个解决方案。
我注意到的第一件事是,当您进行连接时,您没有合并 @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)
【讨论】:
你是对的。但这只是我忘记在上面的代码中复制的东西。我尝试了与提供的链接完全相同的解决方案。如果您检查,您会发现原作者使用 ISNULL 来解决您提到的这个确切问题。尽管如此,问题仍然存在,我仍然得到“与 from 子句结合使用时,在 SELECT 语句中分配的变量不能包含在表达式或赋值中。” 另外,有一点需要澄清。我无法打印这两个变量的结果,因为查询在到达该点之前失败。我尝试删除 @Columnname + ',' 语句,并且查询确实有效。然而,它只列出了它找到的第一个 [Period],并没有“累积”所有找到的 [Period] 你是说在你到达EXEC sp_executesql @DynamicPivotQuery
之前查询就失败了?
您的示例图片和查询不匹配(列名)。如果我们没有正确的架构,那就更难提供帮助了。
如果您有新版本,您可能需要使用 STRING_AGG set @ColumnName = (select string_agg(QUOTENAME(periodo),',') from (select distinct periodo from FACT_Socios_Resumen_Periodo) t)
以上是关于尝试使用动态透视查询时出现语法错误的主要内容,如果未能解决你的问题,请参考以下文章
对指定 VALUE 使用 UPDATE 时出现 Amazon Redshift 语法错误