2017-02-20 92 views
-1

我创建了一个存储过程来处理那些表上的数据。我是否应该避免在SQL中使用循环?

为了让我处理这些数据,我必须做一个while循环,因为我必须计算一个表上不存在的结束日期。

第一条记录的结束日期应该是第二条记录的开始日期-1天。

现在,当我向大四介绍这件事时,他告诉我,在存储过程中使用循环是个很大的问题。我所提供的解决方案是使用该表创建一个视图,并在其上创建多个联合以生成我需要的缺失数据。

我的循环方法错了吗?我今后是否应该避免在我的存储过程中使用循环?

+2

SQL是声明;存储过程是程序性的。我会尽我所能去看看在我使用存储过程之前是否可以声明性地满足要求。没有循环。 – duffymo

+2

循环往往不是一个不错的选择。尝试没有一个。循环中的“逐行”处理也称为“缓慢” –

+0

而不是使用循环,可以使用窗口化表达式('over ... partition')或使用复杂连接。循环使用90%的情况在SQL中不是很好的做法。 – Fka

回答

1

在处理可能需要循环的问题时,使用基于集合的方法总是一个好主意。

几乎总是你的while/for循环可以与条件连接交换来使其基于set。如果它是您需要的计数器,请尝试使用计数表。一个循环的

实施例转化使用JOIN设置的问题是像下面

SELECT DISTINCT A.StartDate, B.EndDate 
FROM 
A LEFT JOIN B 
ON DATEDIFF(d,A.EndDate,B.StartDate)=1 
1

它始终是更好为包括代码,与样品数据一起说明你的情况,并与样品结果描述您想要的结果为给定的样本数据设置。参见:How to post a tsql question on a public forumHow-to-Ask

它几乎是总是比较好避免任何种类的whilecursor。在你描述的情况下,我相信你可以通过利用lead()窗口函数来避免while循环或多个union查询。

实施例使用lead()common table expression:使用在派生表/联视图一个lead()

;with cte as (
    select t.* 
    , NextStartDate = lead(StartDate) over (
     partition by ForEachOfThisColumn -- e.g. AccountId, AssignmentId 
     order by StartDate asc 
    ) 
    from t 
) 
select cte.* 
    , EndDate = dateadd(day, -1, NextStartDate) 
from cte; 

实施例:

select cte.* 
    , EndDate = dateadd(day, -1, NextStartDate) 
from (
    select t.* 
    , NextStartDate = lead(StartDate) over (
     partition by ForEachOfThisColumn -- e.g. AccountId, AssignmentId 
     order by StartDate asc 
    ) 
    from t 
) as cte;