Reputation: 119
Unfortunatly I have to provide a query result in a 3 column format for a external application.
Example:
DECLARE @tmp TABLE ( id INT
, somevalue VARCHAR(30) )
INSERT @tmp
VALUES ( 1, 'Text1' )
, ( 2, 'Text2' )
, ( 3, 'Text3' )
, ( 4, 'Text4' )
, ( 5, 'Text5' )
, ( 6, 'Text6' )
, ( 7, 'Text7' )
, ( 8, 'Text8' )
, (12, 'Text12')
, (13, 'Text13')
SELECT *
FROM @tmp
But I need a resultset like this:
|ID1 |SOMEVALUE1|ID2 |SOMEVALUE2|ID3 |SOMEVALUE3|
|1 |Text1 |2 |Text2 |3 |Text3 |
|4 |Text4 |5 |Text5 |6 |Text6 |
|7 |Text7 |8 |Text8 |12 |Text12 |
|13 |Text13 |null|null |null|null |
What is the best way to format a result set from a flat table in that manner?
Upvotes: 0
Views: 1659
Reputation: 4187
DECLARE @tmp TABLE ( id INT
, somevalue VARCHAR(30) )
INSERT @tmp
VALUES ( 1, 'Text1' )
, ( 2, 'Text2' )
, ( 3, 'Text3' )
, ( 4, 'Text4' )
, ( 5, 'Text5' )
, ( 6, 'Text6' )
, ( 7, 'Text7' )
, ( 8, 'Text8' )
, ( 9, 'Text9' )
;WITH cte AS(
SELECT *, ROW_NUMBER() OVER (ORDER BY id)%3 rn3
FROM @tmp
),
cteR1 AS(
SELECT c1.id, c1.somevalue, ROW_NUMBER() OVER (ORDER BY c1.id) AS rn
FROM cte c1
WHERE c1.rn3 = 1
),
cteR2 AS(
SELECT c1.id, c1.somevalue, ROW_NUMBER() OVER (ORDER BY c1.id) AS rn
FROM cte c1
WHERE c1.rn3 = 2
),
cteR3 AS(
SELECT c1.id, c1.somevalue, ROW_NUMBER() OVER (ORDER BY c1.id) AS rn
FROM cte c1
WHERE c1.rn3 = 0
)
SELECT R1.id, R1.somevalue, R2.id, R2.somevalue, R3.id, R3.somevalue
FROM cteR1 R1
JOIN cteR2 R2 ON R1.rn = R2.rn
JOIN cteR3 R3 ON R1.rn = R3.rn
Upvotes: 0
Reputation: 2315
First set up a cte using your table, and a row_number column in case you have gaps in your id column. I've ordered by id, as I've assumed that's the ordering you want.
Then, join on that cte 3 times, one for each of the column groups you need. The first column will have row_numbers 1,4,7 etc - basically each multiple of 3, plus one. The other columns can be found because they are one and two rows after that.
with cte as (
SELECT ROW_NUMBER() over (order by id) as rowno, *
FROM @tmp
)
select a.id ID1, a.somevalue SOMEVALUE1, b.id ID2, b.somevalue SOMEVALUE2, c.id ID3, c.somevalue SOMEVALUE3
from cte a
left join cte b on b.rowno = a.rowno + 1
left join cte c on c.rowno = a.rowno + 2
where a.rowno % 3 = 1
If you don't have a perfect multiple of 3 in entries, you will just get nulls in the additional columns.
Upvotes: 3
Reputation: 4048
In this way you will spread values on 3 columns
WITH
r as (
select *, ROW_NUMBER() over (order by id) n
from tmp
)
SELECT T1.ID ID1, T1.SOMEVALUE SOMEVALUE1, T2.ID ID2, T2.SOMEVALUE SOMEVALUE2, T3.ID ID3, T3.SOMEVALUE SOMEVALUE3
FROM r T1
LEFT JOIN r t2 ON (T2.n = T1.n+1)
LEFT JOIN r t3 ON (T3.n = t2.n+1)
WHERE (T1.n % 3) = 1
ORDER BY T1.id
Upvotes: 3