簡體   English   中英

SQL Server 2008 - 條件查詢

[英]SQL Server 2008 - Conditional Query

SQL不是我的強項之一。 我有一個SQL Server 2008數據庫。 此數據庫具有一個存儲過程,該過程接收八個int參數。 為了保持這個問題的重點,我將使用這些參數之一作為參考:

@isActive int

這些int參數中的每一個都是-1,0或1. -1表示“未知”或“不關心”。 基本上,我需要查詢一個表,如果int參數是非-1,我需要在我的WHERE子句中考慮它。 因為有8個int參數,所以IF-ELSE語句似乎不是一個好主意。 與此同時,我不知道怎么做呢?

如果參數不等於值,在SQL中是否有一種優雅的方式來添加WHERE條件?

謝謝!

動態搜索條件的最佳來源:

Erland Sommarskog在T-SQL中的動態搜索條件

如果可以使用索引,對於如何執行此操作有很多微妙的含義。 如果您使用的是SQL Server 2008的正確版本,則只需向查詢添加OPTION (RECOMPILE) ,並在運行時將局部變量的值用於優化。

考慮到這一點, OPTION (RECOMPILE)將采用此代碼(其中沒有索引可用於此混亂的OR ):

WHERE
    (@search1 IS NULL or Column1=@Search1)
    AND (@search2 IS NULL or Column2=@Search2)
    AND (@search3 IS NULL or Column3=@Search3)

並在運行時優化它(假設只有@ Search2傳入一個值):

WHERE
    Column2=@Search2

並且可以使用索引(如果在Column2上定義了一個索引)

WHERE coalesce(active,1) = (CASE 
                              WHEN @isActive = -1 THEN coalesce(active,1)
                              ELSE @isActive
                            END)

模式(column = @param OR @param IS NULL)將為您提供可選參數。 您可以使用NULLIF來中和您的-1 更好的是允許空參數,而不是使用幻數

WHERE
   (Customer.IsActive = NULLIF(@isActive, -1) OR NULLIF(@isActive, -1) IS NULL)

而不是使用-1表示你不知道或不關心,如何只使用Null? 幾乎就是為它做的。 然后你可以切換到Bit而不是Int。

另外,我確信TomTom會不同意,但我認為使用CASE語句是實現這一目標的方法。

您的里程可能會有所不同,但似乎查詢引擎處理它比在IsNull中包裝內容或具有多個OR語句要好得多,當您開始添加其他條件時,這可能會變得相當混亂。

無論你走哪條路,執行計划都會受到影響,具體取決於你傳遞的內容,但它不應該太糟糕了。

使用CASE語句的額外好處是,您可以添加一些復雜性而無需額外的代碼(與一堆OR語句相比)。 此外,匹配您的標准的第一個條件可以阻止額外的評估,這在處理OR時並非總是如此......

因此,對於8個可選參數,使用-1作為忽略搜索的值,最終得到的結果是:

WHERE
        @Search1 = CASE WHEN @Search1 = -1 THEN @Search1 ELSE @Column1 END
    AND @Search2 = CASE WHEN @Search2 = -1 THEN @Search1 ELSE @Column2 END
    AND @Search3 = CASE WHEN @Search3 = -1 THEN @Search1 ELSE @Column3 END
    AND @Search4 = CASE WHEN @Search4 = -1 THEN @Search1 ELSE @Column4 END
    AND @Search5 = CASE WHEN @Search5 = -1 THEN @Search1 ELSE @Column5 END
    AND @Search6 = CASE WHEN @Search6 = -1 THEN @Search1 ELSE @Column6 END
    AND @Search7 = CASE WHEN @Search7 = -1 THEN @Search1 ELSE @Column7 END
    AND @Search8 = CASE WHEN @Search8 = -1 THEN @Search1 ELSE @Column8 END

注意:正如KM指出的那樣,如果您正在使用的列可能具有NULL值,則NULL方法不足,因為NULL = NULL將無法正確評估。 所以,為了好玩,我把答案改回原來的海報要求的內容,即使用自己的標識符來跳過搜索。

.... Where field=case @isActive WHEN -1 THEN field ELSE @isActive END ....

沒有一種優雅的方式 - 所有方式都很糟糕。

WHERE @isActive == -1 OR isActive = @isActive

基本上是唯一的方法 - 但即便如此,請確保每次都重新評估查詢計划,否則大多數查詢將使用錯誤的查詢計划。

這是存儲過程不好的經典案例。 查詢是否應該使用存儲過程來完成恕我直言,因為現代 - 大約15年前,當有人足夠聰明地編寫第一個ORM時開始。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM