2012-05-10 9 views
0

一部の日付に基づいて真または偽、または0または1を返す関数を記述しようとしています。たとえば、開始日が&で、終了日が "Mar 01 2010" & "2010年3月2日"かどうかを確認したいとします。 2012年1月1日〜12月30日の日付範囲の場合、日付範囲が '2011年1月1日から2011年12月30日'の場合はtrue、そうでない場合はfalseを返します。次のSQL関数を最適化する方法

現在、そして私はそれが最適化されていない感じ、あなたがこれを何度も呼び出しているいくつかの時間を取って

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 

答えて

2

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

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

この式がtrueを返します2つの範囲が重複している場合は

編集:here is a discussion written much better than i could ever do

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

1

このようなシーンでこの機能を使用しないでください!それはあなたのSQLに直接&を参照してください違いは、SQLインデックスはSQL関数のapplicaleされていないために!

+0

スカラー関数を使用しないように具体的には言います。テーブル・ファンクションでこれをすべてラップすると、パフォーマンスが低下することはなく、テーブル/ビューと同様にパラメータを使用してロジックを再利用できます。 – JeffO

0

私が見ていることは、実際には「完全な」重なりまたは部分的な重なりを見ているかどうかということです。

例:3月1日〜3月3日は、3月2日〜3月4日の範囲を確認していればtrueになりますか?

これが当てはまる場合は、「部分的な」重複をさらに確認する必要があります。

いずれの場合も、この機能を削除する必要があります。

関連する問題