0

いくつかの日付に基づいて true または false または 0 または 1 を返すことができる関数を作成しようとしています。たとえば、「2010 年 3 月 1 日」と「2010 年 3 月 2 日」の開始日と終了日が日付範囲内にあるかどうかを確認したいとします。したがって、日付範囲が「2012 年 1 月 1 日 - 2012 年 12 月 30 日」の場合は true を返します。それ以外の場合、日付範囲が「2011 年 1 月 1 日」から 2011 年 12 月 30 日」の場合は false を返します。

現在、私は以下を使用していますが、最適化されておらず、これを何度も呼び出すと時間がかかると感じています。

CREATE FUNCTION dbo.tmpfnIsDateInRange (@rangeStart    DATETIME, 
                                     @rangeEnd      DATETIME, 
                                     @chkStart      DATETIME, 
                                     @chkEnd        DATETIME) 
   RETURNS TINYINT 
AS 
   BEGIN 
      RETURN CASE 
                WHEN @chkStart BETWEEN @rangeStart AND @rangeEnd 
                     OR @chkEnd BETWEEN @rangeStart AND @rangeEnd 
                THEN 
                   1 
                WHEN @chkStart <= @rangeStart AND @chkEnd >= @rangeEnd 
                THEN 
                   1 
                ELSE 
                   0 
             END; 
   END 
4

3 に答える 3

2

範囲の重複を探している場合、適切なテストは次のようになります。

return case when @chkStart <= @rangeEnd 
             and @chkEnd >= @rangeStart
            then 1
            else 0
            end

この式は、2 つの範囲がオーバーラップしている場合に true を返します。

編集:これは、私がこれまでにできたよりもはるかに優れた議論です

しかし、最大の利点は、関数を完全に削除し、この式 (大文字と小文字の部分を保存) をクエリのフィルターとして直接使用することです。これにより、クエリ オプティマイザーがその名前のとおりに実行できるようになります。

于 2012-05-10T21:39:08.293 に答える
1

そのようなシナリオでは機能を使用しないでください!! SQLで直接実行して違いを確認してください。これは、SQLインデックスがSQL関数に適用されないためです!!!

于 2012-05-10T22:08:01.843 に答える
0

私が確認することの 1 つは、実際に「完全な」オーバーラップを見ているのか、それとも部分的なオーバーラップを見ているのかということです。

例: 3 月 2 日から 3 月 4 日の範囲をチェックしている場合、3 月 1 日から 3 月 3 日は true を返しますか?

その場合は、「部分的な」オーバーラップをさらにチェックする必要があります。

どちらの場合も、関数を削除する必要があります。

于 2012-05-10T22:16:37.280 に答える