0

予選:

このアプリケーションは、アタッチされたクライアント 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 挿入を実行すると時間がかかります。どうすればこれをスピードアップできますか?

4

1 に答える 1

2

各行を個別に挿入する必要がありますか?使えない

insert into LocationConditions 
   SELECT 
      PolicyID, 
      LocID, 
      CONDITIONID, 
      case when (STATECODE = 'TX' AND COUNTY = 'Harris County') OR STATECODE = 'FL' then 1
           else 0 
      end, 
      Included 
   FROM Location loc 

?挿入ステートメントをどのように作成しているかを示していないため、各行に依存しているかどうかはわかりません。

于 2013-02-19T15:38:37.223 に答える