SQL Server 中的动态数据透视表

Posted

技术标签:

【中文标题】SQL Server 中的动态数据透视表【英文标题】:Dynamic Pivot Table in SQL Server 【发布时间】:2012-09-14 19:04:35 【问题描述】:

您好,我有下表,我想将 EcoYear 旋转到顶部,但没有固定的年份,这些年份可以随时开始。此外,不同的案例会有不同的起始年份,所以我需要它填充 0 而不是 null。

CaseID EcoYear NetInv NetOil NetGas
38755   2006   123     2154         525 
38755   2007   123     2154         525 
38755   2008   123     2154         525 
38755   2009   123     2154         525 
38755   2010   123     2154         525 
38755   2011   123     2154         525 
38755   2012   123     2154         525 
38755   2013   123     2154         525 
38755   2014   123     2154         525 
38755   2015   123     2154         525 
38755   2016   123     2154         525 
38755   2017   123     2154         525 
38755   2018   123     2154         525 
38755   2019   123     2154         525 
38755   2020   123     2154         525 

我需要表格如下所示:

CaseID Item 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 
38755 NetInv
38755 NetOil
38755 NetGas

这最初是通过 Access 使用交叉表完成的。

【问题讨论】:

简短回答 - 不要在 SQL Server 中执行此操作,而是在您用于呈现数据的任何应用程序中执行此操作。 我的任务是在 SQL Server 中完成,因为开发人员无法在新版本中使用 Access。谢谢! 搜索“动态 sql”“Pivot”应该会告诉你如何去做。试一试,遇到任何问题都回来 Simple way to transpose columns and rows in Sql?的可能重复 【参考方案1】:

这可以在 sql server 中使用UNPIVOTPIVOT 完成。静态版本是您知道要转换的列的地方:

select *
from 
(
  select CaseId, EcoYear, val, item
  from yourtable
  unpivot
  (
    val
    for Item in (NetInv, NetOil, NetGas)
  )u
) x
pivot
(
  max(val)
  for ecoyear in ([2006], [2007], [2008], [2009], [2010], [2011],
                 [2012], [2013], [2014], [2015], [2016], [2017],
                 [2018], [2019], [2020])
) p

见SQL Fiddle with Demo

动态版本将确定执行记录:

DECLARE @colsPivot AS NVARCHAR(MAX),
    @colsUnpivot as NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @colsPivot = STUFF((SELECT distinct ',' + QUOTENAME(EcoYear) 
                    from yourtable
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

select @colsUnpivot = stuff((select ','+quotename(C.name)
         from sys.columns as C
         where C.object_id = object_id('yourtable') and
               C.name LIKE 'Net%'
         for xml path('')), 1, 1, '')


set @query 
  = 'select *
      from
      (
        select caseid, ecoyear, val, col
        from yourtable
        unpivot
        (
          val
          for col in ('+ @colsunpivot +')
        ) u
      ) x1
      pivot
      (
        max(val)
        for ecoyear in ('+ @colspivot +')
      ) p'

exec(@query)

见SQL Fiddle with Demo

【讨论】:

谢谢。这正是我需要做的。这个动态版本是否能够为可能在 2006 年之后开始的其他案例添加额外的列?例如,如果它从 2008 年开始,它将持续到 2022 年,但对于 2006 和 2007 列将只显示零。并感谢您的帮助。我将以此作为我其他报告的基础! @RolandP 它将为您在EcoYear 中的任何字段添加列,然后您可以根据需要限制年份。

以上是关于SQL Server 中的动态数据透视表的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server 中具有动态列的数据透视表

MS SQL Server 中的动态数据透视

SQL Server 中的数据透视表查询

SQL Server 中的动态透视列

SQL Server 数据库中的动态数据透视

SQL Server 2016 中的数据透视表