I'm looking for you, SQL Experts (or maybe this is a quite easy problem, than of course everyone is welcome :) )
I start with the following table:
ID|Contract Start Date|Runtime (Months)|MonthCount
1 |2015-04-01 |48 |1
2 |2018-02-01 |36 |1
I want to create a table which creates (inserts) new rows based on the recoreds in the column Contract Start Date and Runtime. In other words I need to create a row for each month starting from the startdate unitl the number of runtime is reached.
ID|Contract Start Date|Runtime (Months)|MonthCount
1 |2015-04-01 |48 |1
1 |2015-05-01 |48 |1
1 |2019-04-01 |48 |48
2 |2018-02-01 |36 |1
2 |2018-03-01 |36 |2
2 |2021-03-01 |36 |36
I tried achiving this with nested cursor and while loops, this works somehow; 'the only issue' is, that I create a cartesian product/duplicate records.
While researching I found this: While loop creating duplicate records; but I'm not shure how to apply this to my code
SQL:
DECLARE @ID INT
DECLARE @ContractStartDate DATE
DECLARE @ContractRuntime INT
DECLARE @MonthCount INT
--Declaring Cursor
DECLARE MonthCursor CURSOR
FOR SELECT * FROM LeasingData
OPEN MonthCursor
FETCH NEXT FROM MonthCursor
INTO @ID,@ContractStartDate, @ContractRuntime, @MonthCount
WHILE @@FETCH_STATUS = 0
BEGIN
WHILE @MonthCount < @ContractRuntime
BEGIN
SET @MonthCount = @MonthCount + 1
SET @ContractStartDate = DATEADD(month, 1, @ContractStartDate)
INSERT INTO Table
SELECT @ID,@ContractStartDate, @ContractRuntime, @MonthCount
END
FETCH NEXT FROM MonthCursor
INTO @ID,@ContractStartDate, @ContractRuntime, @MonthCount
END
CLOSE MonthCursor
DEALLOCATE MonthCursor
This results in:
ID|Contract Start Date|Runtime (Months)|MonthCount
1 |2015-04-01 |48 |1
1 |2015-05-01 |48 |2
1 |2015-06-01 |48 |3
1 |2015-06-01 |48 |3
1 |2015-06-01 |48 |3
1 |2015-06-01 |48 |3
1 |2015-07-01 |48 |4
1 |2015-07-01 |48 |4
1 |2015-07-01 |48 |4
1 |2015-07-01 |48 |4
1 |2015-07-01 |48 |4
1 |2015-07-01 |48 |4
and so on....
Maybe I'm completly on the wrong path with my solution. Glad to learn something new :)
WHILEloop is most definitely the worst way to do this, I'm afraid. A Tally table would be a far better option.