Reputation: 1040
I have data like this:
Year Q1 Q2 Q3 Q4
------------------------------------
2000 421 123 145 126
2000 422 124 146 127
2000 423 125 147 128
2000 424 126 148 129
2001 425 127 149 130
2001 426 128 150 131
2001 427 129 151 132
2002 428 130 152 133
2002 429 131 153 134
How do I get it like this:
Year Q1 Q2 Q3 Q4 Year Q1 Q2 Q3 Q4 Year Q1 Q2 Q3 Q4
--------------------------------------------------------------------------------------------------------
2000 421 123 145 126 2001 425 127 149 130 2002 428 130 152 133
2000 422 124 146 127 2001 426 128 150 131 2002 429 131 153 134
2000 423 125 147 128 2001 427 129 151 132
2000 424 126 148 129
I visited this:https://www.databasejournal.com/features/mssql/converting-rows-to-columns-pivot-and-columns-to-rows-unpivot-in-sql-server.html
but no success.
May I can do that with PIVOT
But I am not been able to do that. Please suggest me. Thanks in Advance.
Upvotes: 0
Views: 51
Reputation: 95620
This is an ugly solution, in all honesty, and I don't really know why you'd want data to look like this. The ORDER BY
in the OVER
clause is a total guess, mind:
WITH VTE AS(
SELECT *
FROM (VALUES(2000,421,123,145,126),
(2000,422,124,146,127),
(2000,423,125,147,128),
(2000,424,126,148,129),
(2001,425,127,149,130),
(2001,426,128,150,131),
(2001,427,129,151,132),
(2002,428,130,152,133),
(2002,429,131,153,134)) V ([Year], Q1, Q2, Q3, Q4)),
RNs AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY [Year] ORDER BY Q1) AS RN --ORDER BY is total guess
FROM VTE)
SELECT RN1.[Year], RN1.Q1, RN1.Q2, RN1.Q3, RN1.Q4,
RN2.[Year], RN2.Q1, RN2.Q2, RN2.Q3, RN2.Q4,
RN3.[Year], RN3.Q1, RN3.Q2, RN3.Q3, RN3.Q4
FROM RNs RN1
LEFT JOIN RNs RN2 ON RN1.[Year] = RN2.[Year] - 1
AND RN1.RN = RN2.RN
LEFT JOIN RNs RN3 ON RN1.[Year] = RN3.[Year] - 2
AND RN1.RN = RN3.RN
WHERE RN1.[Year] = (SELECT MIN(sq.[Year])
FROM RNs sq)
ORDER BY RN1.RN;
This will also not work as intended if a year after the lowest has more rows that the first one (for example, if 2003 had 5 rows, you would only get 4). This could be handled, if really needed.
Edit: IT's still ugly, but this helps when you have more row later on:
WITH VTE AS(
SELECT *
FROM (VALUES(2000,421,123,145,126),
(2000,422,124,146,127),
(2000,423,125,147,128),
(2000,424,126,148,129),
(2001,425,127,149,130),
(2001,426,128,150,131),
(2001,427,129,151,132),
(2002,428,130,152,133),
(2002,429,131,153,134),
(2003,429,132,154,135),
(2003,430,133,155,136),
(2003,431,134,156,137),
(2003,432,135,157,138),
(2003,433,136,158,139)) V ([Year], Q1, Q2, Q3, Q4)),
RNs AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY [Year] ORDER BY Q1) AS RN --ORDER BY is total guess
FROM VTE),
Tally AS (
SELECT DISTINCT RNs.RN, Y.MinYear
FROM RNs
CROSS APPLY (SELECT MIN(Year) AS MinYear FROM RNs) Y)
SELECT RN1.[Year], RN1.Q1, RN1.Q2, RN1.Q3, RN1.Q4,
RN2.[Year], RN2.Q1, RN2.Q2, RN2.Q3, RN2.Q4,
RN3.[Year], RN3.Q1, RN3.Q2, RN3.Q3, RN3.Q4,
RN4.[Year], RN4.Q1, RN4.Q2, RN4.Q3, RN4.Q4
FROM Tally T
LEFT JOIN RNs RN1 ON T.RN = RN1.RN
AND RN1.[Year] = T.MinYear
LEFT JOIN RNs RN2 ON T.MinYear = RN2.[Year] - 1
AND T.RN = RN2.RN
LEFT JOIN RNs RN3 ON T.MinYear = RN3.[Year] - 2
AND T.RN = RN3.RN
LEFT JOIN RNs RN4 ON T.MinYear = RN4.[Year] - 3
AND T.RN = RN4.RN
ORDER BY T.RN;
Upvotes: 1