2016-01-21 59 views
2

我在下面的SELECT語句中加入了幾個表,它有三個參數。在WHERE子句中應用條件過濾

DECLARE @Jobid  INT=0, 
     @leadid  INT=0, 
     @employeeid INT=0 

SELECT e.id, 
     l.id, 
     j.id, 
     e.NAME, 
     l.NAME, 
     j.NAME 
FROM employee e 
     INNER JOIN leads l 
       ON e.leadid = l.id 
     INNER JOIN Jobs j 
       ON j.id = e.Jobid 

這工作正常,沒有過濾。

在WHERE子句中,我必須添加如下所示的內容。如果三個ID中的任何一個大於零,那麼我必須考慮WHERE子句中的過濾器;如果它等於零,我不會考慮這個特定的條件。

If @jobid> 0 
then introduce this condition in where clause ([email protected]) 

If @leadid> 0 
then introduce this condition in where clause ([email protected]) 

If @employeeid> 0 
then introduce this condition in where clause ([email protected]) 

我知道如何通過動態SQL來實現這一點,但我需要一個靜態SQL語句來實現這一點。

我試過如下:

where 
((J.Id = @Jobid and @Jobid>0) 
or @Jobid=0) 
and (
(L.Id = @leadid and @leadid>0) 
or @leadid=0 
) 
and (
(e.Id = @employeeid and @employeeid >0) 
or @employeeid =0 
) 

但是有一個性能命中。

請在靜態SQL中建議我使用其他更好的方法,特別是使用Case When

+0

選中此問題[答案](http://stackoverflow.com/questions/34730633/how-to-add-to-where-clause-depending-on-parameter-value/34730678#34730678)。 –

+1

只要'(J.Id = @Jobid或@ Jobid = 0)'等也會做同樣的事情。 (不知道它是否會更快,但...) – jarlh

+0

@Mihail:我不是在尋找動態SQL – StackUser

回答

0

可以使用CASE表達式所示:

CASE例

WHERE 
    CASE 
     WHEN @Jobid > 0 THEN @Jobid  -- When @Jobid supplied use it. 
     ELSE J.id      -- When not; return current value. 
    END = J.id 

當@Jiobid超過0它是相對於J.id.當不把J.id與自身進行比較時,這當然會導致匹配。

我個人更喜歡@jarlh在上面評論中提出的方法。簡單性使代碼更容易遵循。

@jarlh例

WHERE 
    (J.Id = @Jobid or @Jobid=0) 

如果這些方法不能提高你的表現嘗試添加您的架構和一些樣本記錄的問題。你也可以考慮發佈執行計劃。

+0

非常感謝你 – StackUser

+0

你也應該看看@ZoharPeled的答案。他/她在使用0. –

+0

時說得很好。關於這個答案的一件事 - 在目標列(在本例中爲J.Id)可爲空的情況下,它可能會導致錯誤的結果,因爲null = null會評估爲假。除此之外,在測試案例時,我發現在性能方面沒有任何變化......在版本方面,所以這是作者認爲更可讀的問題。 –

4

首先,這個((J.Id = @Jobid and @Jobid>0) or @Jobid=0)可以替換
與此(@Jobid = 0 or J.Id = @Jobid)。 注意,由於0顯然不是作業ID(或員工或潛在客戶)的有效值,該and部分是無關緊要的,因爲沒有記錄將永遠包含0

二的ID,不要使用0作爲一個無效的值,請改用null。它不會影響性能,但它是一種更好的編程習慣,因爲0在其他情況下可能非常有用。

第三,衆所周知的查詢遭遇性能問題,特別是在存儲過程中,因爲緩存的執行計劃可能不是當前執行的最佳選擇。據我所知,處理這個問題的最佳方法是在查詢中添加重新編譯提示,如this articlethat article中所建議的。

所以,我建議你查詢,看起來像這樣:

CREATE PROCEDURE <procedure name> 
(
     @Jobid  INT=NULL, 
     @leadid  INT=NULL, 
     @employeeid INT=NULL 
) 
AS 

SELECT e.id, 
     l.id, 
     j.id, 
     e.NAME, 
     l.NAME, 
     j.NAME 
FROM employee e 
     INNER JOIN leads l 
       ON e.leadid = l.id 
     INNER JOIN Jobs j 
       ON j.id = e.Jobid 
WHERE (@Jobid IS NULL OR J.Id = @Jobid) 
AND (@leadid IS NULL OR l.Id = @leadid) 
AND (@employeeid IS NULL OR e.Id = @employeeid) 
OPTION(RECOMPILE) 

GO 

選擇性能通常與表的索引正確提高。但是,索引正確要求知識並非所有開發人員都有。這是一個值得一讀的主題。我會start here

+0

非常感謝您的建議。我已經選擇了目標數據答案。無論如何,我會投票。 – StackUser