I need to convert the following table
quarter cal_year blue green yellow red
DEC 2011 +31% 25-30% 22-24% -21%
MAR 2012 +61% 50-60% 43-49% -42%
into this. Is there a simple way to achieve it?
Color DEC MAR
blue +31% +61%
green 25-30% 50-60%
yellow 22-24% 43-49%
red -21% -42%
While @Joro's version will work, I would do this slightly different since CTE is not needed in this case.
Static Version of the PIVOT
where you know the columns to transform:
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
Dynamic Version where the columns are determined at run-time:
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)
If you only have a few columns, then you can also do this with a CASE
statement and a 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
Here is one way to do this:
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
But let's suppose that you have more data to compare:
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
Note, you should optimize the last example if you like it to work with same months from different years.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.