2012-05-10 71 views
0

我正在嘗試編寫一個函數,它可以根據某些日期返回true或false或0或1。因此,假設您想要檢查例如「2010年3月」&「Mar 02 2010」的開始日期是否在日期範圍內。所以如果你的日期範圍是「2012年1月1日 - 2012年12月30日」,那麼它將返回true,否則如果日期範圍是'2011年1月1日'到2011年12月30日'那麼它將返回錯誤。如何優化以下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如果兩個範圍以任何方式重疊。

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

但是,最大的收穫是完全刪除函數,並直接在查詢中使用此表達式(保存case部分)作爲過濾器,因爲這樣可以使查詢優化器按名稱執行操作。

1

千萬不要在這樣的場景中使用該功能!直接在你的sql &看到的區別,它是因爲sql索引不適用於sql函數!!!

+0

我會特別說避免使用標量函數。在表函數中包裝所有這些不應該妨礙性能,並且允許邏輯被類似地重用到表/視圖中,但是具有參數。 – JeffO

0

我會看到的一件事是,你是否真的在看「完整」重疊或部分重疊。

例如:如果您在3月2日至3月4日檢查範圍,3月1日至3月3日是否會恢復正常?

如果是這種情況,則必須對「部分」重疊進行更多檢查。

無論哪種情況,您都應該刪除該功能。