2012-07-30 42 views
3

我經常遇到在那裏我可以寫一個T-SQL查詢這樣的條件的情況下...CASE或AND/OR在哪裏條件。最佳做法是什麼?

DECLARE @FirstName NVARCHAR(500)  
SET @FirstName ='Joe' 

SELECT * 
FROM dbo.Customers c 
WHERE 
    CASE 
     WHEN @FirstName <> '' THEN 
      CASE WHEN c.FirstName= @FirstName THEN 1 ELSE 0 END 
     ELSE 1 
    END = 1 

或者這樣......

SELECT * 
FROM dbo.Customers c 
WHERE 
    (@FirstName = '' OR (@FirstName <> '' AND c.FirstName = @FirstName)) 

它們都可以產生相同的結果和兩個查詢計劃似乎都是相同的。

所以我很好奇哪一個是最好的做法,或者如果有一個比另一個有任何陷阱?

+2

最佳做法是解決客戶問題,而不是擔心同樣有效的SQL語法 – Andomar 2012-07-30 15:43:16

+0

首先擔心清楚地表達邏輯的意圖。 – HABO 2012-07-30 15:56:54

+3

最佳做法是不使用。或者可能是第二個與「OPTION(RECOMPILE)」一起使用的。即使在查找特定值時,也不會在'c.FirstName'上使用索引。參見[T-SQL中的動態搜索條件](http://www.sommarskog.se/dyn-search.html)和[Catch-all queries](http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries /)的一些文章。 – 2012-07-30 16:16:14

回答

3

我認爲這也是關於可讀性的大部分情況,但在第一個查詢示例中您做得更多。你迫使數據庫爲每行創建一個0或1的值,並要求數據庫檢查值是0還是1.在我看來,創建查詢的步驟越少越好。

我會選擇第二種方法,雖然你也許可以擺脫@firstName <的>',因爲它是不必要的,所以你的查詢清理多一點:

SELECT * 
FROM dbo.Customers c 
WHERE 
    (@FirstName = '' OR c.FirstName = @FirstName) 

編輯:馬丁·史密斯提供一個非常好的見解,你可能要考慮。

+0

+1(我顛倒了這兩個條件的順序,以便首先引用c.FirstName。)我喜歡你將它包裝在parens中,因爲它明確表示這種方法可以擴展到允許其他「可選提供」的搜索參數,例如'和(c.LastName = @LastName或@LastName IS NULL)'。 (實際上,我們使用NULL作爲「no argument」值,但它的工作原理是相同的。底線是我們不必根據各種提供的參數動態構建SQL語句。我們只傳入提供的參數值或NULL。 – spencer7593 2012-07-30 18:33:58

+0

有趣的是,我沒有意識到留下@FirstName <>''會產生不同的結果。不比較NULL <>「'評估爲false?這是我所假設的c.FirstName = NULL將始終評估爲。我不知道沒有它,哪些行會返回。我會修改我的答案。謝謝。 – 2012-07-30 19:28:38

+0

我很抱歉,我錯了你的查詢返回不同的結果;你的陳述是相同的。你是正確的,'@FirstName <>'''檢查是多餘的。 (在Oracle中,一個空字符串相當於NULL,但SQL Server或MySQL中不是這種情況)。 (我刪除了我以前的評論 - 我不知道我在想什麼;我會在今天晚上運行測試用例。) – spencer7593 2012-07-30 19:41:24

0

我更喜歡第二種變體 - 將變量默認爲null,因爲在最近的SQL Server構建中有一個可以優化的特定優化。

DECLARE @FirstName NVARCHAR(500) = NULL 

SELECT * 
FROM dbo.Customers c 
WHERE 
    (@FirstName IS NULL OR c.FirstName = @FirstName) 

請參閱本SO回答更多的細節:https://stackoverflow.com/a/3415629/1564603

0

怎麼樣使用LIKE避免空Mathing?

DECLARE @firstName NVARCHAR(500)= NULL

SELECT * FROM Çdbo.Customers WHERE (c.FirstName LIKE @firstName + '%')

我認爲結果可能是一樣的,更有趣 無論搜索時間成本更長的事實

相關問題