2012-10-18 114 views
1

,這是什麼情況下最優化的解決方案:TSQL優化 - WHERE子句不LIKE

在我的查詢的WHERE子句是這樣的:

WHERE columnX LIKE @Account + '%' 

我用 '%',因爲@Account可能'',在這種情況下,我想獲得所有的值。在所有其他情況下,我可以使用equals(=)。

該溶液沒有被優化,因爲我有columnX指數和我想用,因爲其等於(=)。另外,由於性能原因,OR方案是不可接受的。

你有其他建議嗎?我在WHERE子句中用CASE試過,但沒有找到優化的好解決方案。我們的兼容級別是80,因此不能使用更新的語法。 (不要問爲什麼:-))

TnX提前!

維迪奇

+0

爲什麼不能通過if(@Account ='')語句將它分成兩個部分(查詢)?所以如果@ Account =''你根本不需要WHERE子句。 – Kaf

+0

這是解決方案之一,但它看起來像代碼冗餘和性能不太好。另外,因爲這段代碼在程序中,所以我需要在兩種不同的情況下添加WITH RECOMPILE,因爲執行計劃不同。 –

+0

在構建查詢的代碼中,測試帳戶是空白還是空白,然後重定向以運行查詢,該查詢說明獲取所有行。否則,請使用where columnX = Account。 –

回答

2

你可以試試這個

where columnX = isnull(nullif(@Account, ''), columnX) 
+0

即使這個解決方案沒有提高我的查詢的性能,這個語法是非常有趣和有用的! –

0

這是一個情況下,我們都面臨着:)

有沒有什麼可以做的確實,如果你有什麼用像選擇。你的情況並不是最糟糕的,如果你只在最後加上%,這個指數很可能會被用於尋找。真正的問題是,如果開始時有%,那麼索引(如果使用的話)將在掃描時也將被掃描,請記住,索引使用也與您選擇的列有關。如果你有一個帶有ID和Name的表,並且有一個名字索引,並且選擇*,那麼索引可能不會被使用。

要完成,你可以考慮全文搜索,但它的實現是相當複雜的

0

試試這個

DECLARE @var VARCHAR(10) = '' 
DECLARE @table TABLE (ID VARCHAR(10)) 

INSERT INTO @table 
SELECT '11' 
UNION 
SELECT '2' 

SELECT * 
FROM @table 
WHERE (Len(@var) = 0 OR ID = @var) 

SET @var = '11' 

SELECT * 
FROM @table 
WHERE (Len(@var) = 0 OR ID = @var) 
1

您正試圖執行兩個不同語義查詢;一個拉動所有的行,一個拉動一個行。這兩個查詢將按照定義有兩個不同的查詢計劃。您試圖將它們組合成一個查詢以避免「代碼重複」被誤導。 「代碼重複」是不是敵人,複雜性是。答案是你爲每個場景創建一個存儲過程。這不僅允許每個存儲過程代表一個查詢計劃,您還將按照single responsibility principle簡化您的申請。

+0

感謝您回答代碼重複和SRP。由於具體情況,我無法創建兩個程序,但我會在程序中保留IF ELSE,並添加WITH RECOMPILE以避免執行計劃出現問題。 –