予選:
このアプリケーションは、アタッチされたクライアント SQL Server 2005 または 2008 データベースからデータを読み取ることができますが、一時テーブルを使用する以外は変更を加えません。サーバー上の独自のデータベースにテーブルを作成できます。
このソリューションは、SQL Server 2005 で機能する必要があります。
スキーマ:
これは、スキーマの単純化されたアイデアです。
グループ- 場所のグループの特性を定義します
場所- 1 つの地理的場所の特性を定義します。グループテーブルにリンクします。
GroupCondition - グループへのリンク。そのグループに属する場所のサブセットに適用されるメジャーを定義します。
GroupConditionCriteria - GroupCondition テーブルへのリンク。where 句の単一の句の属性、値、関係演算子、およびブール演算子に名前を付けます。名前付き属性はすべて Location テーブルのフィールドです。シーケンス番号があります。GroupConditionCriteria の複数の行を適切な順序で並べて、完全なフィルター条件を形成する必要があります。このフィルター条件は、GroupCondition に関連付けられたグループの一部である場所に暗黙的に制限されます。フィルター基準を満たす場所レコードは「含まれる」、そうでない場所レコードは「除外される」です。
目標:
既存のクエリの多くは、ロケーション テーブルから属性を取得します。「含まれる」ロケーションの GroupCondition 情報を提供する何か (テーブル、一時テーブル、クエリ、CTE、openquery、UDF など) に結合したいと考えています。(場所は複数のルールに含めることができますが、それは別の問題です。)
私が欲しいもののスキーマは次のとおりです。
CREATE TABLE #LocationConditions
(
[PolicyID] int NOT NULL,
[LocID] int NOT NULL,
[CONDITIONID] int NOT NULL,
[Satisfies Condition] bit NOT NULL,
[Included] smallint NOT NULL
)
PolicyID はグループを識別し、LocID は場所を識別し、CONDITIONID は GroupCondition を識別します。フィルタに場所レコードが含まれている場合、[条件を満たしている] は 1 です。(含まれているのは、フィルター条件の強制オーバーライドを含む別のルール テーブルから派生したものです。この説明では重要ではありません。)
問題のサイズ:
これまでのところ、このようなテーブルを作成できるよう最善を尽くしていますが、遅いです。私がテストしている現在のデータベースでは、潜在的に一致するルール (GroupConditions) によって影響を受ける (含まれるか除外される) 50,000 の場所があります。実行時間は 4 分です。定期的な更新を行い、永続的なテーブルを使用する場合、これはうまくいく可能性がありますが、より高速なものを望んでいます。
私が試したこと:
フィルター条件のいくつかの部分を 1 つの大きなフィルター条件に連結するために、一連の CTE を使用しました。そのうちの 1 つは再帰的です。そのような状態の例として:
(STATECODE = 'TX' AND COUNTY = 'Harris County') OR STATECODE = 'FL'
フィルター条件には 1 ~ 5 個のフィールドを指定でき、それらをグループ化するために任意の数の括弧を使用できます。サポートされている演算子は、lt、le、gt、ge、=、<>、AND、および OR です。
条件を取得しても、それはまだテキスト文字列なので、insert ステートメントを作成します (動的に実行する必要があります)。
insert into LocationConditions
SELECT
1896,
390063,
38,
case when (STATECODE = 'TX' AND COUNTY = 'Harris County') OR STATECODE = 'FL' then 1
else 0
end,
1
FROM Location loc
WHERE loc.LocID = 390063
最初に #InsertStatements という独自の一時テーブルに挿入ステートメントを追加し、カーソルを使用してそれらをループ処理します。EXEC を使用して各挿入を実行します。
CREATE TABLE #InsertStatements
(
[Insert Statement] nvarchar(4000) NOT NULL
)
-- Skipping over Lots of complicated CTE's to add to #InsertStatements
DECLARE @InsertCmd nvarchar(4000)
DECLARE InsertCursor CURSOR FAST_FORWARD
FOR
SELECT [Insert Statement]
FROM #InsertStatements
OPEN InsertCursor
FETCH NEXT FROM InsertCursor
INTO @InsertCmd
WHILE @@FETCH_STATUS = 0
BEGIN
--PRINT @InsertCmd
EXEC(@InsertCmd)
FETCH NEXT FROM InsertCursor
INTO @InsertCmd
END
CLOSE InsertCursor
DEALLOCATE InsertCursor
SELECT *
FROM #LocationConditions
ORDER BY PolicyID, LocID
ご想像のとおり、50,000 の動的 SQL 挿入を実行すると時間がかかります。どうすればこれをスピードアップできますか?