1

我尝试在此网站上遵循其他几个建议,但由于某种原因无法使其工作。

基本上我试图从这个任务表中得到:

| 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 做另一个枢轴,但这不会给我一行。

我也无法理解如何首先不旋转桌子将我带到我需要的地方,就像其他一些帖子中针对类似问题的建议一样。

如果有一种可扩展的方式来做到这一点(比如旋转更多的列),那就太好了。

谢谢。

4

1 回答 1

2

您可以获得所需的结果,但由于您需要在多列 (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 函数应用于 get max(value)for each col

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 Fiddle with Demo

如果每个项目的值数量有限,上述版本会很好用ProjectId,但如果每个项目的任务数量未知,则需要使用动态 SQL 来获得最终结果:

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

请参阅SQL Fiddle with Demo。这些将给出结果:

| PROJECTID |                   TYPE0DATE1 |                 TYPE0DATE2 |                   TYPE2DATE1 |                 TYPE2DATE2 |                   TYPE4DATE1 |                 TYPE4DATE2 |
|-----------|------------------------------|----------------------------|------------------------------|----------------------------|------------------------------|----------------------------|
|         1 | April, 12 2013 00:00:00+0000 | May, 08 2013 00:00:00+0000 | April, 20 2013 00:00:00+0000 | May, 17 2013 00:00:00+0000 | April, 01 2013 00:00:00+0000 | May, 06 2013 00:00:00+0000 |
于 2013-11-07T14:13:00.530 回答