毎日夜に実行されるスケジュールされたジョブを開発する必要がありました。タスクは完了しましたが、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)