Reputation: 425
I have to split a row into multiple rows based on a count column. if count is 6 , row should split into 2, first row's count will be 5 and next will be 1. If count is 17, there will be 4 split, 3 rows with 5 each and last count will be 2.
Table will have 2 columns :
id CNT
------------
10 17
Above row should split into 4 like below:
id CNT
--------------------
10 5
10 5
10 5
10 2
I have tried using mod and division to find the total number of split but could not find final solution.
Please provide your input to achieve this.
Upvotes: 0
Views: 1280
Reputation: 60462
DarkRob's recursive query can be simplified to
WITH RECURSIVE cte AS
(
SELECT id
-- remainder or 5 if no remainder
,CASE WHEN Cnt MOD 5 = 0 THEN 5 ELSE Cnt MOD 5 END AS val
-- how many rows left?
,(Cnt - val) / 5 AS x
FROM tab
WHERE Cnt > 0
UNION ALL
SELECT id, 5, x - 1
FROM cte
WHERE x > 0
)
SELECT *
FROM cte
But I would prefer (ab)using Teradata's Time Series Expansion feature:
SELECT tab.*,
End(pd) - Begin(pd) AS val
FROM tab
WHERE Cnt > 0
-- create one rows for each group of 5 (days)
EXPAND ON PERIOD(DATE, DATE + Cnt) AS pd BY INTERVAL '5' DAY
Upvotes: 1
Reputation: 3833
You may try this. I am not sure about the syntax used in teradata
, but this will surely give you idea about how you can sort out your problem.
First we need to find the quotient and remainder portion of each number with respect to the id. Then quotient is the number of times you want to repeat your loop, for which we are using recursive cte
and remainder is the last row need to be added to get the sum of numbers equal to your value.
Sample query will be like this.
declare @tab table ( id int, num int )
insert into @tab ( id, num )
values ( 1, 17 )
, ( 2, 22 )
; with cte as (
select id, num , num %5 as remainder, num/5 as quo from @tab )
, ct (sl, id, num, val) as (
select 1 as sl, id, num, 5 as val from cte
union all
select c.sl+1, t.id, t.num, c.val from cte as t inner join ct as c on t.id=c.id where c.sl<t.quo
)
, cfinal (id, num, val) as (
select id, num, val from ct
union all
select id, num, remainder from cte
)
select * from cfinal order by id, val desc
Result
id num val
----------- ----------- -----------
1 17 5
1 17 5
1 17 5
1 17 2
2 22 5
2 22 5
2 22 5
2 22 5
2 22 2
Upvotes: 2