I have the following data
x
+--------+
| orders |
+--------+
| S1 |
| S2 |
| S3 |
| S4 |
| S5 |
| S6 |
| S7 |
| S8 |
| S9 |
| S10 |
| S11 |
| S12 |
+--------+
I am required to return the result as follows – fit five rows in one column:
+-----------------+
| Orders |
+-----------------+
| S1,S2,S3,S4,S5 |
| S6,S7,S8,S9,S10 |
| S11,S12 |
+-----------------+
There is nothing to group on or segregate these into rows. So I assigned a row_number and did mod 5 on the row_number. It almost works, but not quite.
Here is what I have tried:
;with mycte as (
select
'S1' as orders
union all select
'S2'
union all select
'S3'
union all select
'S4'
union all select
'S5'
union all select
'S6'
union all select
'S7'
union all select
'S8'
union all select
'S9'
union all select
'S10'
union all select
'S11'
union all select
'S12'
)
,mycte2 as (
Select
orders
,ROW_NUMBER() over( order by orders) %5 as rownum
from mycte
)
select distinct
STUFF((
SELECT ',' + mycte2.orders
FROM mycte2
where t1.rownum= mycte2.rownum
FOR XML PATH('')
), 1, 1, '') orders
, rownum
from mycte2 t1
the result is :
+-----------+--------+
| orders | rownum |
+-----------+--------+
| S1,S3,S8 | 1 |
| S10,S4,S9 | 2 |
| S11,S5 | 3 |
| S12,S6 | 4 |
| S2,S7 | 0 |
+-----------+--------+
Can someone please show me how to get to my desired result?
Advertisement
Answer
How about
CREATE TABLE T
([orders] varchar(3));
INSERT INTO T
([orders])
VALUES
('S1'),
('S2'),
('S3'),
('S4'),
('S5'),
('S6'),
('S7'),
('S8'),
('S9'),
('S10'),
('S11'),
('S12');
WITH CTE AS
(
SELECT Orders,
(ROW_NUMBER() OVER(ORDER BY LEN(Orders)) - 1) / 5 RN
FROM T
)
SELECT STRING_AGG(Orders, ',')
FROM CTE
GROUP BY RN
ORDER BY RN;
OR
SELECT STUFF(
(
SELECT ',' + Orders
FROM CTE
WHERE RN = TT.RN
FOR XML PATH('')
), 1, 1, ''
) Orders
FROM CTE TT
GROUP BY RN
ORDER BY RN;
You can use
(SELECT 1)
instead ofLEN(Orders)
Returns:
+-----------------+
| Orders |
+-----------------+
| S1,S2,S3,S4,S5 |
| S6,S7,S8,S9,S10 |
| S11,S12 |
+-----------------+