在T-SQL中避免循环

时间:2011-11-18 19:08:38

标签: performance tsql while-loop set-based

我需要制定一份每天晚上执行的预定工作。我已完成任务但必须使用While循环。这让我觉得"有罪"。我需要一些关于如何将此操作转换为基于集合的操作并提高性能的建议。

我的表看起来像(尽可能简化):

T_POOL
PoolID | ContactID | ContactState
  1    |     1     |      1
  1    |     2     |      1
  1    |     3     |      1
  2    |     4     |      2
  2    |     5     |      3

 T_POOL_DEC
 PoolID | Layer4ID
   1    |    1
   2    |    3
   3    |    5

 T_LAYER4
 Layer4ID | ConditionValue1(Count) | ConditionValue2(Month)
    1     |       5                | 3

我使用while循环的原因是检索相对于PoolID的ContactID值(作为一个组)。 在临时表中存储不同的poolID值并在循环中获取这些poolID值。所以我的While循环遍历PoolID的不同值(不是逐行循环遍历所有表) 我正在进行更新操作,可以证明:

  While (True)
    Take Next @PoolID

    Update T_Pool TP SET ContactState ={some value} 
    INNER JOIN T_POOL_DEC PD ON PD.PoolID = TP.PoolID
    INNER JOIN T_LAYER4 L4 ON L4.Layer4ID = PD.Layer4ID
    Where {COUNT(TP.ContactID) >= L4.ConditionValue1 
    AND ContactID.CreateDate >=DATEADD(MM,L4.ConditionValue2*-1,GETDATE()}
    AND PoolID = @PoolID

    If it has passed through all available PoolIDs, break;
  END

我希望我能够尽可能清楚地证明这种情况,因为我无法在这里写下所有的查询。

修改评论 忘了添加,什么阻止我更新整个表是,PoolID是一个FK以上。每个PoolID都有一个Layer4ID,我根据PoolID的Layer4值对Pool中的每个ContactID进行一些计算(比如计算池中每个联系人的状态,并检查计数结果是否相等或者大于其Pool的Layer4值。编辑我的表演示部分更清晰。

因此,从上面可以看出,每个Pool都有一个Layer4ID。并且每个Layer4都有一些条件,在这种情况下它们都是整数(ConditionValue1表示要更新的ContactID的最小计数(更新T_POOL表中的状态我的意思)和ConditionValue2表示每个联系人的当前日期的过去月数被视为有效。(更新其状态) - 从自己的表中检索ContactID的创建日期.-

EDIT2 在我的示例查询中添加了一些连接(忽略语法错误,分组等)

EDIT3

我当前的查询可以看作如下:简单地说,这需要被释放"来自while循环,即消除@PoolID用法。

UPDATE T_POOL SET ContactState= 4
WHERE PoolID= @PoolID AND ContactState=2
AND EXISTS(
SELECT T.ContactID FROM(
   SELECT TP.ContactID,
      L4.ConditionValue1,
      COUNT(TP.ContactID) OVER (PARTITION BY TP.PoolID) AS TOTAL_CONTACT_COUNT
   FROM Contact C
   INNER JOIN T_POOL TP ON TP.ContactID= C.ContactID
   INNER JOIN T_POOL_DEC PD ON PD.PoolID = TP.PoolID
       INNER JOIN T_LAYER4 L4 ON L4.Layer4ID = PD.Layer4ID
   WHERE PD.PoolID= @PoolID AND TP.State=2 AND TP.LOG_STATUS NOT IN (9,10) AND  C.LOG_CREATE_DATE >= DATEADD(MM,L4.ConditionValue2*-1,GETDATE()))T 

 WHERE T.TOTAL_CONTACT_COUNT>=T.ConditionValue1 AND C.ContactID= ContactID)

0 个答案:

没有答案