当前使用游标和临时表的SQL替代方法

时间:2016-05-12 20:22:03

标签: sql-server performance tsql cursors

我正在清理之前员工留下的一些存储过程,并遇到了一个我试图确定是否有一种方法可以在不使用游标的情况下处理它的方法。目前,游标会查看具有每条记录的开始日期和结束日期的临时表。然后它获取记录的ID并创建一个行,其中包含每个日期的ID和日期,该日期属于start&的范围。结束日期。

然后使用此数据创建另一个临时表,该临时表存储记录的ID和每个ID的不同日期的计数。

我是否可以在开始日期和结束日期之间的日期部分日期执行datediff?我觉得必须有一个更好的方法来获取这些信息,但我担心我可能会过度简化并丢失一些东西。

以下是现在的代码:

declare @StartDate datetime, @EndDate datetime, @ID bigint, @WSIdAndDates cursor 

set @WSIdAndDates = cursor fast_forward for
select servicestartdate, serviceenddate, WorksheetID from #que_rp_claims_dates 

open @WSIdAndDates
fetch next from @WSIdAndDates into @StartDate, @EndDate, @ID 
while @@FETCH_STATUS = 0
begin

        with ctedaterange 
            as (select [Dates]=@StartDate, 
                @ID[workSheetid]

            union ALL

            select [dates] + 1,
                @ID[workSheetid]
            from ctedaterange 
            where [dates] + 1 <= @EndDate) 

            insert into #tempworksheetidanddates
            select [workSheetid],
                [dates] 
            from ctedaterange 
        option(maxrecursion 0)

    fetch next from @WSIdAndDates into @StartDate, @EndDate, @ID 
end

close @WSIdAndDates
deallocate @WSIdAndDates

select worksheetid, count(distinct(dates)) as LOS into ##que_rp_claims_LOS 
from #tempworksheetidanddates
group by worksheetid

表格##que_rp_claims_LOS是唯一一个在此代码段之外使用的表格。另一个临时表被删除。

非常感谢任何见解或建议。

2 个答案:

答案 0 :(得分:3)

该过程正在从#que_rp_claims_dates获取ID以及开始和结束日期,并为此打开一个光标。

每行都完成相同的操作:递归CTE正在收集/计算从开始日期到结束日期的所有日期,并将其填入表格中。

在最后一步中,您只能提供身份证和天数。

所以我认为你是对的......如果你的中间结果(临时表)在其他任何地方都不需要,那么计算每个ID的DATEDIFF就足够了。

注意

如果使用DATETIME个值,结果可能取决于实际时间(如果时间不是全天)。仔细看看这个!

顺便说一下:感谢你为摆脱糟糕的结构所做的努力!

答案 1 :(得分:2)

临时表的更好替代方法是使用表变量。你可以像这样声明一个表变量:

DECLARE @tempVariable table(
    WorksheetID int,
    servicestartdate DATE,
    serviceenddate DATE
);

就光标而言,您始终可以将所有数据插入表变量中,使用一段时间迭代它并在处理完后立即删除条目。像这样:

while exists (select top 1 * from tempVariable)
begin
    select top 1 @StartDate = servicestartdate, @EndDate = serviceenddate, @ID = WorksheetID from @tempVariable

    //your code

    DELETE TOP(1) FROM @tempVariable;
end