基于单列旋转多列

时间:2013-11-07 12:12:55

标签: sql sql-server sql-server-2008-r2 pivot

我尝试在本网站上提出其他几条建议,但由于某些原因,我不能做这项工作。

基本上我正试图从这个任务表中获取:

| TaskID | ProjectID | TaskType | TaskDate1 | TaskDate2 |
---------------------------------------------------------
|      1 |         1 |    Type4 |  20130401 |  20130506 |
|      2 |         1 |    Type0 |  20130412 |  20130508 |
|      3 |         1 |    Type2 |  20130420 |  20130517 |

那个:

| ProjectID | Type0Date1 | Type0Date2 | Type2Date1 | Type2Date2 | Type4Date1 | Type4Date2 |
---------------------------------------------------------
|         1 |   20130412 |   20130508 |   20130420 |   20130517 |   20130401 |   20130506 |

每个项目必须具有多个预定义任务(由其类型标识)。这些任务有很多属性,但我对2个日期感兴趣,每个项目将它们全部放在一行会很好。

我可以轻松地将其转移到以下列之一:PIVOT (MAX(TaskDate1) FOR TaskType IN ([Type0],[Type2],[Type4]))

我尝试复制TaskType列并为TaskDate2围绕它做另一个转轴,但这不会给我一行。

我也无法理解如何将表格首先转移到我需要的位置,就像其他一些帖子中提出类似问题的建议一样。

如果有一种可扩展的方法(如旋转甚至更多的列),那么很高兴知道。

感谢。

1 个答案:

答案 0 :(得分:1)

您可以获得所需的结果,但由于您需要在多列(TaskDate1TaskDate2上进行PIVOT),我首先将两列拆分为多行。

由于您使用的是SQL Server 2008+,因此可以使用UNPIVOT函数或CROSS APPLY来转换多列。基本语法为:

select projectid,
  col = TaskType+col,
  value
from yourtable
cross apply
(
  values 
    ('Date1', TaskDate1),
    ('Date2', TaskDate2)
) c(col, value)

SQL Fiddle with Demo。这会将您的数据转换为易于使用的格式:

| PROJECTID |        COL |                        VALUE |
|-----------|------------|------------------------------|
|         1 | Type4Date1 | April, 01 2013 00:00:00+0000 |
|         1 | Type4Date2 |   May, 06 2013 00:00:00+0000 |
|         1 | Type0Date1 | April, 12 2013 00:00:00+0000 |
|         1 | Type0Date2 |   May, 08 2013 00:00:00+0000 |

获得此格式的数据后,您可以将PIVOT函数应用于获取每个max(value)的{​​{1}}:

col

请参阅SQL Fiddle with Demo

如果每个select projectId, Type0Date1, Type0Date2, Type2Date1, Type2Date2, Type4Date1, Type4Date2 from ( select projectid, col = TaskType+col, value from yourtable cross apply ( values ('Date1', TaskDate1), ('Date2', TaskDate2) ) c(col, value) ) d pivot ( max(value) for col in (Type0Date1, Type0Date2, Type2Date1, Type2Date2, Type4Date1, Type4Date2) ) piv; 的值数量有限,则上述版本将运行良好,但如果每个项目的任务数量未知,则需要使用动态SQL来获得最终结果:

ProjectId

SQL Fiddle with Demo。这些将产生结果:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(TaskType+col) 
                    from yourtable
                    cross apply
                    (
                      select 'Date1', 1 union all
                      select 'Date2', 2
                    ) c(col, so)
                    group by col, tasktype, so
                    order by tasktype, so
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT projectid, ' + @cols + ' 
            from 
            (
              select projectid,
                col = TaskType+col,
                value
              from yourtable
              cross apply
              (
                values 
                  (''Date1'', TaskDate1),
                  (''Date2'', TaskDate2)
              ) c(col, value)
            ) x
            pivot 
            (
                max(value)
                for col in (' + @cols + ')
            ) p '

execute sp_executesql @query