ここで最初に考えたのは、パフォーマンスの問題は何ですか?確かに、クエリを実行するループ内に (行ごとに 1 回適用する) ループがあります。しかし、不十分な実行計画を取得していませんか?結果セットは膨大ですか?しかし、ジェネリックに目を向けましょう。一度この問題をどのように解決しますか? SQL は実際にはメモ化を行いません (著名な @Martin_Smith が指摘しているように)。それで、男の子は何をするのですか?
オプション 1 - 新しいデザイン
まったく新しいデザインを作成します。この特定のケースでは、@Aaron_Bertrand は、カレンダー テーブルがニーズを満たす可能性があると指摘しています。その通りです。これはカレンダー以外の状況ではあまり役に立ちませんが、SQL ではよくあることですが、少し考え方を変える必要があります。
オプション 2 - UDF の呼び出しを減らす
この関数を呼び出すアイテムのセットを絞り込みます。これは、 ページング/行カウント .必要な個別の値を持つ小さな結果セットを生成しますそして UDF を呼び出して、数回しか呼び出されないようにします。これはオプションである場合とそうでない場合がありますが、多くのシナリオで機能します。
オプション 3 - 動的 UDF
私はおそらくこの提案のために部屋からブーイングされるでしょうが、ここに行きます.この UDF を遅くしているのは、ループ内の select ステートメントです。 Holiday テーブルが頻繁に変更されない場合は、テーブルにトリガーを設定できます。トリガーは、UDF を書き出して更新します。新しい UDF は、すべての休日の決定をブルート フォースする可能性があります。 SQL を書く SQL で共食いに少し似ているでしょうか?もちろん。ただし、サブクエリを取り除き、UDF を高速化します。やじを始めましょう。
オプション 4 - メモする
SQL は直接メモ化できませんが、SQL CLR はあります。 UDF を SQL CLR udf に変換します。 CLR では、静的変数を使用できます。 Holidays テーブルを一定の間隔で簡単に取得して、ハッシュテーブルに格納できます。次に、CLR でループを書き直します。適切なロジックであれば、さらに進んで回答全体をメモすることもできます。
更新:
オプション 1 - 上記で使用した関数の例ではなく、ここでは一般的なことに集中しようとしていました。ただし、UDF の現在の設計では、Holiday テーブルへの複数の呼び出しが連続してヒットした場合に許容されます。 「悪い日」とそれに対応する「翌営業日」のリストを含むある種のカレンダー スタイル テーブルを使用すると、複数のヒットやクエリの可能性を排除できます。
オプション 3 - ドメインは事前に不明ですが、休日のテーブルを変更することは十分に可能です。特定の休日については、対応する次の稼働日が含まれます。このデータから、下部に長い case ステートメント ('5/5/2012' の後に '5/14/2012' など) を含む UDF を吐き出すことができます。この戦略は、すべてのタイプの問題に有効であるとは限りませんが、一部の問題には有効です。
オプション 4 - すべてのテクノロジーに影響があります。 CLR を展開する必要があり、SQL Server の構成を変更し、SQL CLR は 3.5 フレームワークに制限されています。個人的には、これらの調整は十分に簡単だと思いますが、状況は異なる場合があります (たとえば、反抗的な DBA や、運用サーバーへの変更に対する制限など)。
静的変数を使用するには、アセンブリ be が必要です完全な信頼を付与 .ロックが正しく設定されていることを確認する必要があります。
いくつかの証拠 非常に高い トランザクション レベル CLR は直接 SQL ほどには機能しません。ただし、あなたのシナリオでは、あなたがしようとしていること (メモ化) に対する直接的な SQL 相関関係がないため、この観察は当てはまらない可能性があります。