2013-05-22 68 views
3

在此存儲過程中,在where條件中,如果@startDate和@EndDate值爲null,那麼如何使用COALESCE來處理它。在日期字段中的可爲空值的存儲過程

CREATE PROCEDURE dbo.SP_ManageLeaveSearch 

    @StartDate datetime, 
    @EndDate datetime, 

    @UserName CHAR(100), 
    @MarketID INT 

AS 
BEGIN 
    SELECT d1.UserName,c1.HouseName,c.StartDate,c.EndDate 
     FROM table1 c  
     Inner JOIN table2 d1 ON c.UserID = d1.UserID 


WHERE 
    (

     (
      (@StartDate BETWEEN StartDate AND EndDate) 
      OR 
      (@EndDate BETWEEN StartDate AND EndDate) 
      OR 
       (
       (@StartDate <= Startdate AND @EndDate>=EndDate) 
       ) 
     ) 
     AND 
     (

      d1.UserName = COALESCE(@UserName, d1.UserName) 
     ) 

) 

END 

提前告誡。

+1

備註:您應該**不要**爲存儲過程使用'sp_'前綴。微軟已經保留了這個前綴以供自己使用(參見*命名存儲過程*)](http://msdn.microsoft.com/en-us/library/ms190669%28v=sql.105%29.aspx),以及你將來有可能冒着名字衝突的風險。 [這對你的存儲過程性能也是不利的](http://www.sqlperformance.com/2012/10/t-sql-queries/sp_prefix)。最好只是簡單地避免使用'sp_'並將其他內容用作前綴 - 或者根本沒有前綴! –

回答

4

這應該爲你工作:

CREATE PROCEDURE dbo.ManageLeaveSearch 

    @StartDate datetime = NULL, 
    @EndDate datetime = NULL, 

    @UserName CHAR(100) = NULL, 
    @MarketID INT 

AS 
BEGIN 
    SELECT d1.UserName,c1.HouseName,c.StartDate,c.EndDate 
     FROM table1 c  
     Inner JOIN table2 d1 ON c.UserID = d1.UserID 


WHERE 
    COALESCE(@StartDate,StartDate) <= EndDate AND 
    StartDate <= COALESCE(@EndDate,EndDate) AND 
    d1.UserName = COALESCE(@UserName, d1.UserName) 

END 

注:

  • 不要名存儲過程與sp_前綴 - 它是保留給Microsoft的system procedures
  • 我已經用簡單的條件來確定重疊的存在。如果範圍1在範圍2結束之前開始,則在兩個範圍之間存在重疊,範圍2在範圍1結束之前開始。
  • 我已經爲那些應該爲空的參數指定了默認值。
+0

在這種情況下沒有得到開始日期和結束日期都是同一天的記錄。 –

+0

@Ashok - 這只是將'<'改成'<=',我現在已經完成了。您沒有真正定義您的輸入,並且我沒有仔細考慮原始查詢中的邊緣條件。很容易調整(通過使用'<或'<='決定)是否希望範圍的端點是包含性的或排它性的。通常,如果還有時間分量,那麼您可能希望'@ endDate' /'EndDate'是獨佔的,不包括在內。 –

1

嘗試這一個 -

CREATE PROCEDURE dbo.usp_ManageLeaveSearch 

    @StartDate DATETIME, 
    @EndDate DATETIME, 

    @UserName CHAR(100), 
    @MarketID INT 

AS BEGIN 

    SELECT 
      d1.UserName 
     , c.HouseName 
     , c.StartDate 
     , c.EndDate 
    FROM dbo.table1 c  
    JOIN dbo.table2 d1 ON c.UserID = d1.UserID 
    WHERE d1.UserName = ISNULL(@UserName, d1.UserName) 
     AND (
       ISNULL(@StartDate, StartDate) BETWEEN StartDate AND EndDate 
      OR 
       ISNULL(@EndDate, EndDate) BETWEEN StartDate AND EndDate 
     ) 

END 
+0

如果參數爲空,是否可以省略比較日期的條件?說'@StartDate爲空或(@StartDate在StartDate和EndDate之間)''。請原諒。 – shahkalpesh

+0

@shahkalpesh,當然是。 – Devart

1

您已經過於複雜的事情。這應該適用於你,並且就我所知的查詢而言簡單。我更喜歡這種語法,因爲在我的大部分用例中,...... OR @UserName IS NULL可以在執行之前從查詢中刪除,從而實現非常簡單,快速的執行。

CREATE PROCEDURE dbo.SP_ManageLeaveSearch 

    @StartDate datetime, 
    @EndDate datetime, 

    @UserName CHAR(100), 
    @MarketID INT 

AS 
BEGIN 
SELECT d1.UserName,c1.HouseName,c.StartDate,c.EndDate 
FROM table1 c  
JOIN table2 d1 
    ON c.UserID = d1.UserID 
WHERE (@StartDate<=EndDate OR @StartDate IS NULL) 
AND (@EndDate>=StartDate OR @EndDate IS NULL) 
AND (d1.UserName = @UserName OR @UserName IS NULL) 
END 
+0

這個想法是,如果'@ StartDate'和'@ EndDate'都是NULL,查詢預處理器會在完成日期檢查之前優化整個日期檢查,甚至開始執行實際查詢。如果一個是NULL,但另一個不是,那麼查詢將通過執行索引範圍掃描以最佳方式在StartDate和/或EndDate上使用任何索引,對於UserName也是如此。如果它是NULL,'@ UserName'在查詢甚至開始之前將被優化,如果它不是NULL,那麼它可以優化使用UserName列上的任何索引。 –

+0

此次顯示結果不正確,當用戶輸入的開始日期和結束日期爲 –

+0

對不起,我對其進行了更正。 –