2

毎日夜に実行されるスケジュールされたジョブを開発する必要がありました。タスクは完了しましたが、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 値を (グループとして) 取得するためです。個別のプール ID 値を一時テーブルに格納し、これらのプール ID 値をループでフェッチします。したがって、While ループは、プール ID の個別の値をループします (すべてのテーブルを行ごとにループするのではありません)。更新操作を実行しています。のように示すことができます:

  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 値に応じて、プール内の各 ContactID に対していくつかの計算を行っています (状態に応じてプール内の各連絡先をカウントし、カウント結果が等しいかそれより大きいかどうかを確認するなど)。そのプールの Layer4 値より明確にするために、テーブルのデモンストレーション部分を編集します。

上記のように、各プールには Layer4ID があります。そして、各 Layer4 にはいくつかの条件があります。この場合、それらは両方とも整数です (ConditionValue1 は、更新される ContactID の最小数を示します (つまり、T_POOL テーブルの状態を更新します)。ConditionValue2 は、各連絡先の現在の日付から過去の月数を示します)。 (状態を更新するため) -ContactIDの作成日を自身のテーブルから取得-

Edit2 サンプルクエリにいくつかの結合を追加しました(構文エラー、グループ化などを無視します)

編集3

私の現在のクエリは次のように見ることができます: 簡単に言うと、これは 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)
4

0 に答える 0