【问题标题】:Dynamic Pivot Error in sql serversql server中的动态数据透视错误
【发布时间】:2020-06-10 17:21:28
【问题描述】:

我使用了链接中的上述代码。但我收到一个错误,因为

消息 8156,级别 16,状态 1,第 14 行“工厂”列是 为“p”指定了多次

Efficiently convert rows to columns in sql server

这是我的桌子:

测试

ID      score    Check      TotalofScore
------  -----    -------    ------------
867439  1        factory        1
867439  1        Plant          1
867442  1        factory        1
867442  1        Plant          1
923991  1        Warehouse      1
923991  1        Plant          1
923930  1        factory        1
923930  1        Plant          1
923101  1        Warehouse      1
923101  1        Plant          1

这是我的尝试

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

SELECT @cols = Stuff((SELECT ',' + Quotename([check])
                      FROM   TEST
                      GROUP  BY [Check],
                                [ID]
                      ORDER  BY [ID]
                      FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')

SET @query = N'SELECT ' + @cols + N' from 
             (SELECT TEST.[ID],
                     Score,
                     [check],
                     [Total Of Score] = Count(TEST.Score) over(partition by [ID], [score], [check])
             FROM TEST) T
            pivot 
            (
             SUM (T.[score])
             for T.[check] in (' + @cols + N') ) p '

EXEC Sp_executesql @query; 

预期结果:

ID       TotalofScore   factory     Plant   Warehouse
------   ------------   -------     -----   ---------
867439      1             1 
867439      1                                   1
867442      1                       1
867442      1                                   1
923991      1             1 
923991      1             1
923930      1                       1
923930      1                       1
923101      1              1
923101      1                                   1

【问题讨论】:

  • @Bluefeet 这是我需要帮助的那个。

标签: sql sql-server pivot


【解决方案1】:

如错误中所述,您不能在 Pivot 中多次指定相同的列名,如

..pivot (SUM (T.[score]) for T.[check] in ([factory,[Plant],[factory]..))p

像这样改变你的@cols初始化

SELECT @cols = Stuff((SELECT DISTINCT ',' + Quotename([check])
                      FROM   TEST
                      FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') 

或者

SELECT @cols = Stuff((SELECT ',' + Quotename([check])
                      FROM   TEST
                      GROUP  BY [Check]
                      FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') 

更新:将Dynamic Pivot转换为过程并将结果插入新表中

create procedure dbname.schemaname.DynamicPivotProcedure 
as
begin
DECLARE @cols  AS NVARCHAR(MAX),
        @query AS NVARCHAR(MAX)

SELECT @cols = Stuff((SELECT ',' + Quotename([check])
                      FROM   TEST
                      GROUP  BY [Check]
                      FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')

SET @query = N'SELECT ID, [Total Of Score],' + @cols + N' from 
             (SELECT TEST.[ID],
                     Score,
                     [check],
                     [Total Of Score] = Count(TEST.Score) over(partition by [ID], [score], [check])
             FROM TEST) T
            pivot 
            (
             SUM (T.[score])
             for T.[check] in (' + @cols + N') ) p '

EXEC Sp_executesql @query; 
end

go
sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO

IF OBJECT_ID('tempdb..#MyTempTable') IS NOT NULL 
begin
DROP TABLE #MyTempTable
end

SELECT * INTO #MyTempTable FROM 
OPENROWSET('SQLNCLI', 'Server=(local)\SQL2008;Trusted_Connection=yes;',
     'EXEC dbname.schemaname.DynamicPivotProcedure')

SELECT * FROM #MyTempTable

【讨论】:

  • SELECT @cols = Stuff((SELECT ',' + Quotename([check]) FROM TEST GROUP BY [Check] , [ID] ORDER BY [ID] FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
  • @Lewan - Mybad 忘记从订单中删除 ID,现在更新检查
  • 它成功了,有没有办法在视图中完成相同的任务。这是动态 sql,我知道它不能在视图中使用。但是有没有另一种方法来完成同样的任务
  • @Lewan 是的,你可以看看这个stackoverflow.com/questions/653714/…
  • @Lewan 将(local)\SQL2012 替换为select @@SERVERNAME 结果并将exec DynamicPivotProcedure 更改为exec databasename.schemaname.DynamicPivotProcedure
【解决方案2】:

GROUP BYORDER By 子句中删除Id。这样您就可以得到DISTINCT 检查列。

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME([check]) 
  from #Sample
  group by [Check]
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')
set @query = N'SELECT  ID, [Total Of Score], ' + @cols + N'  from 
             (
               SELECT 
TEST.[ID],
Score,
[check],
[Total Of Score] = Count(TEST.Score) over(partition by [ID], [score], [check])
FROM #Sample AS TEST
  ) T
  pivot 
  (
     SUM (T.[score])
      for T.[check] in (' + @cols + N')
  ) p '
exec sp_executesql @query;

【讨论】:

  • 这可行,但我错过了 ID 和 TotalOfScore 列,
  • @Lewan:在选择列表中添加列。使用更新后的答案。
  • 完美。 '我假设' + cols + N' 可以解决问题,因为子选择查询具有其中提到的列。我知道这不能在视图中使用。但是有没有在视图中执行相同任务的替代方法。由于不经常推荐使用动态sql。
猜你喜欢
  • 2014-10-16
  • 2014-07-26
  • 1970-01-01
  • 1970-01-01
  • 2013-02-09
  • 2018-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多