带INSERT的嵌套WHILE循环产生重复的记录

时间:2019-08-07 15:07:17

标签: sql sql-server

SQL专家,我正在寻找您(或者这可能是一个非常简单的问题,当然不欢迎大家光临:))

我从下表开始:

ID|Contract Start Date|Runtime (Months)|MonthCount
1 |2015-04-01         |48              |1
2 |2018-02-01         |36              |1

我想创建一个表,该表根据“合同开始日期和运行时间”列中的重新创建(插入)新行。换句话说,我需要从startdate unitl开始为达到运行时间的每个月创建一行。

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

我尝试使用嵌套的游标和while循环来实现这一点,但这在某种程度上是可行的。 “唯一的问题”是,我创建了笛卡尔积/重复记录。

在研究时,我发现了这一点: While loop creating duplicate records;但我不知道如何将此应用于我的代码

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

结果是:

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

以此类推。...

也许我的解决方案完全走错了路。很高兴学到新的东西:)

1 个答案:

答案 0 :(得分:0)

使用递归CTE:

with cte as (
      select id, contract_start_date, runtime, monthcount
      from t
      union all
      select id, dateadd(month, monthcount, contract_start_date), runtime - 1, monthcount
      from cte
      where runtime > 0
    )
select *
from cte
order by id, contract_start_date;

如果您需要超过100个月的时间,请添加option (maxrecursion 0)