2

I am trying to solve a problem. I want to change the rows into columns but I am not sure on how to do this. Pivot is a solution but the columns are not being fetched as I want them to. Here is an example.

The raw data

The table above is the one that I want to use and convert it into something similar to the below one

The resultset

Basicaly the quaters needs to be distributed in years on the same row for the same request ID. I had tried CASE but that seems to be an overkill for something like this.

Here is a fiddle to start with.

Thanks.

2 Answers 2

2

To get fully elastic solution you should search for dynamic pivot. If you know years in advance you could use:

;WITH cte AS
(
   SELECT ReqId,quater1,quater2,quater3,quater4
        ,[q1] = CONCAT('Q1_',[year])
        ,[q2] = CONCAT('Q2_',[year])
        ,[q3] = CONCAT('Q3_',[year])
        ,[q4] = CONCAT('Q4_',[year])
   FROM #forecast
)
SELECT ReqId
    ,[Q1_2014] = MAX([Q1_2014])
    ,[Q2_2014] = MAX([Q2_2014])
    ,[Q3_2014] = MAX([Q3_2014])
    ,[Q4_2014] = MAX([Q4_2014])
    ,[Q1_2015] = MAX([Q1_2015])
    ,[Q2_2015] = MAX([Q2_2015])
    ,[Q3_2015] = MAX([Q3_2015])
    ,[Q4_2015] = MAX([Q4_2015])
    ,[Q1_2016] = MAX([Q1_2016])
    ,[Q2_2016] = MAX([Q2_2016])
    ,[Q3_2016] = MAX([Q3_2016])
    ,[Q4_2016] = MAX([Q4_2016])
    ,[Q1_2017] = MAX([Q1_2017])
    ,[Q2_2017] = MAX([Q2_2017])
    ,[Q3_2017] = MAX([Q3_2017])
    ,[Q4_2017] = MAX([Q4_2017])  
FROM cte
PIVOT (MAX(quater1) FOR [q1] IN ([Q1_2014],[Q1_2015],[Q1_2016],[Q1_2017])) AS pvt1
PIVOT (MAX(quater2) FOR [q2] IN ([Q2_2014],[Q2_2015],[Q2_2016],[Q2_2017])) AS pvt2
PIVOT (MAX(quater3) FOR [q3] IN ([Q3_2014],[Q3_2015],[Q3_2016],[Q3_2017])) AS pvt3
PIVOT (MAX(quater4) FOR [q4] IN ([Q4_2014],[Q4_2015],[Q4_2016],[Q4_2017])) AS pvt4
GROUP BY ReqId

LiveDemo

Output:

╔════════╦══════════╦══════════╦══════════╦══════════╦══════════╦══════════╦══════════╦══════════╦══════════╦══════════╦══════════╦══════════╦══════════╦══════════╦══════════╦═════════╗
║ ReqId  ║ Q1_2014  ║ Q2_2014  ║ Q3_2014  ║ Q4_2014  ║ Q1_2015  ║ Q2_2015  ║ Q3_2015  ║ Q4_2015  ║ Q1_2016  ║ Q2_2016  ║ Q3_2016  ║ Q4_2016  ║ Q1_2017  ║ Q2_2017  ║ Q3_2017  ║ Q4_2017 ║
╠════════╬══════════╬══════════╬══════════╬══════════╬══════════╬══════════╬══════════╬══════════╬══════════╬══════════╬══════════╬══════════╬══════════╬══════════╬══════════╬═════════╣
║     1  ║      10  ║      20  ║      30  ║      40  ║      50  ║      60  ║      70  ║      80  ║      90  ║     100  ║     110  ║     120  ║ (null)   ║ (null)   ║ (null)   ║ (null)  ║
║     2  ║      10  ║      20  ║      30  ║      40  ║      50  ║      60  ║      70  ║      80  ║      90  ║     100  ║     110  ║     120  ║ 130      ║ 140      ║ 150      ║ 160     ║
╚════════╩══════════╩══════════╩══════════╩══════════╩══════════╩══════════╩══════════╩══════════╩══════════╩══════════╩══════════╩══════════╩══════════╩══════════╩══════════╩═════════╝

Addendum 1

Alternatively:

;WITH cte AS (
  SELECT ReqId, [q] ='Q1_' + CAST([year] AS CHAR(4)), quater = quater1  FROM #forecast
  UNION ALL SELECT ReqId, [q] ='Q2_' + CAST([year] AS CHAR(4)), quater2 FROM #forecast
  UNION ALL SELECT ReqId, [q] ='Q3_' + CAST([year] AS CHAR(4)), quater3 FROM #forecast
  UNION ALL SELECT ReqId, [q] ='Q4_' + CAST([year] AS CHAR(4)), quater4 FROM #forecast
)
SELECT *
FROM cte
PIVOT (MAX(quater) FOR q IN (Q1_2014,Q2_2014,Q3_2014,Q4_2014,
                             Q1_2015,Q2_2015,Q3_2015,Q4_2015,
                             Q1_2016,Q2_2016,Q3_2016,Q4_2016,
                             Q1_2017,Q2_2017,Q3_2017,Q4_2017)
) AS pvt;

LiveDemo2

Addendum 2

Dynamic Pivot (you don't need to know years in advance):

DECLARE @sql NVARCHAR(MAX) = N'
WITH cte AS (
  SELECT ReqId,[q] =''Q1_'' + CAST([year] AS CHAR(4)),quater = quater1  FROM #forecast
  UNION ALL SELECT ReqId,[q] =''Q2_'' + CAST([year] AS CHAR(4)),quater2 FROM #forecast
  UNION ALL SELECT ReqId,[q] =''Q3_'' + CAST([year] AS CHAR(4)),quater3 FROM #forecast
  UNION ALL SELECT ReqId,[q] =''Q4_'' + CAST([year] AS CHAR(4)),quater4 FROM #forecast
)
SELECT *
FROM cte
PIVOT (MAX(quater) FOR q IN (<placeholder>)
) AS pvt;';

DECLARE @cols NVARCHAR(MAX) = 
                STUFF((SELECT ',' + QUOTENAME('Q1_' + CAST([year] AS CHAR(4))) +
                              ',' + QUOTENAME('Q2_' + CAST([year] AS CHAR(4))) +
                              ',' + QUOTENAME('Q3_' + CAST([year] AS CHAR(4))) +
                              ',' + QUOTENAME('Q4_' + CAST([year] AS CHAR(4)))
                      FROM (SELECT DISTINCT [year] FROM #forecast) cte
                      ORDER BY [year]
                      FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') , 1, 1, '');

SET @sql = REPLACE(@sql, '<placeholder>', @cols);

EXEC [dbo].[sp_executesql] @sql;

LiveDemo3

Sign up to request clarification or add additional context in comments.

1 Comment

awesome. I created something similar seeing your first answer. I was about to post the solution but I saw your update. Perfect approach thanks.
0

Look That:

Concatenate Rows

Maybe give you a way.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.