3

我需要转换下表

quarter   cal_year  blue    green   yellow  red

DEC 2011        +31%    25-30%  22-24%  -21%

MAR 2012        +61%    50-60%  43-49%  -42%

进入这个。有没有简单的方法来实现它?

Color   DEC     MAR     
blue    +31%    +61%    
green   25-30%  50-60%  
yellow  22-24%  43-49%  
red     -21%    -42%    
4

2 回答 2

3

虽然@Joro 的版本可以工作,但我会做的略有不同,因为在这种情况下不需要 CTE。

PIVOT您知道要转换的列的静态版本:

select col, [Mar], [Dec]
from 
(
  select quarter, val, col
  from yourtable
  unpivot
  (
    val
    for col in (blue, green, yellow, red)
  )u
) x
pivot
(
  max(val)
  for quarter in ([Mar], [Dec])
) p

SQL Fiddle with Demo

在运行时确定列的动态版本:

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

select @colsPivot = STUFF((SELECT distinct ',' + QUOTENAME(Quarter) 
                    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 not in ('Quarter', 'cal_year')
         for xml path('')), 1, 1, '')

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

exec(@query)

SQL Fiddle with Demo

如果你只有几列,那么你也可以用一个CASE语句和一个UNION ALL

select col,
  max(case when quarter = 'MAR' then val end) MAR,
  max(case when quarter = 'DEC' then val end) DEC
from
(
  select quarter, val, col
  from
  (
    select quarter, blue as val, 'blue' as col
    from yourtable
    union all
    select quarter, green as val, 'green' as col
    from yourtable
    union all
    select quarter, yellow as val, 'yellow' as col
    from yourtable
    union all
    select quarter, red as val, 'red' as col
    from yourtable
  ) u
) x
group by col

SQL Fiddle with Demo

于 2012-09-15T12:57:52.840 回答
1

这是执行此操作的一种方法:

DECLARE @SourceTable TABLE
(
    [Quarter] NVARCHAR(20),
    [cal_year] BIGINT,
    [blue] NVARCHAR(20),
    [green] NVARCHAR(20),
    [yellow] NVARCHAR(20),
    [red] NVARCHAR(20)
)

INSERT INTO @SourceTable ([Quarter],[cal_year],[blue],[green],[yellow],[red])
VALUES  ('DEC',2011,'+31%','25-30%','22-24%','-21%')
       ,('MAR',2012,'+61%','50-60%','43-49%','-42%')


;WITH CTE([Quarter],[Color],[Value]) AS
(
    SELECT [Quarter],[Color],[Value]
    FROM
        (
            SELECT [Quarter],[blue],[green],[yellow],[red]
            FROM @SourceTable
        ) data
    UNPIVOT
    (
         [Value] FOR [Color] IN ([blue],[green],[yellow],[red])
    )AS unpvt
)
SELECT *
FROM 
(
    SELECT Color,[Quarter],Value
    FROM CTE
)AS src
PIVOT
(
    MAX(Value) FOR [Quarter] IN ([MAR],[DEC] )

) AS pvtTbl

但是让我们假设您有更多数据要比较:

CREATE TABLE #SourceTable
(
    [Quarter] NVARCHAR(20),
    [cal_year] BIGINT,
    [blue] NVARCHAR(20),
    [green] NVARCHAR(20),
    [yellow] NVARCHAR(20),
    [red] NVARCHAR(20)
)

INSERT INTO #SourceTable ([Quarter],[cal_year],[blue],[green],[yellow],[red])
VALUES   ('DEC',2011,'+31%','25-30%','22-24%','-21%')
        ,('JAN',2012,'+11%','10-20%','13-49%','-12%')
        ,('FEB',2012,'+31%','25-35%','12-14%','-11%')
        ,('MAR',2012,'+71%','10-45%','13-59%','-11%')
        ,('APR',2012,'+11%','15-15%','12-24%','-51%')
        ,('MAY',2012,'+11%','40-60%','13-39%','-43%')


DECLARE @DynamicSQLStatement NVARCHAR(MAX)

SET @DynamicSQLStatement=N';WITH CTE([Quarter],[Color],[Value]) AS
                         (
                             SELECT [Quarter],[Color],[Value]
                             FROM
                                 (
                                     SELECT [Quarter],[blue],[green],[yellow],[red]
                                     FROM #SourceTable
                                 ) data
                             UNPIVOT
                             (
                                    [Value] FOR [Color] IN ([blue],[green],[yellow],[red])
                             )AS unpvt
                         )
                         SELECT *
                         FROM 
                         (
                             SELECT Color,[Quarter],Value
                             FROM CTE
                         )AS src
                         PIVOT
                         (
                             MAX(Value) FOR [Quarter] IN ('+(SELECT SUBSTRING((SELECT '],[' + [Quarter] FROM #SourceTable FOR XML PATH('')),3,200)+']')+')
                         ) AS pvtTbl'

EXECUTE sp_executesql @DynamicSQLStatement


DROP TABLE #SourceTable

请注意,如果您希望它与不同年份的相同月份一起工作,则应该优化最后一个示例。

于 2012-09-15T11:40:43.347 回答