2012-07-03 64 views
1

我傳遞兩個參數ORDER BY子句:使用情況下表達

@Column和@Direction,兩者都是爲nvarchar(50)

我想從選擇查詢更改順序參數內的值。

例如,

if @Column = Name and @Direction = 'Desc' then order by Name desc 
if @Column = Name and @Direction = 'Asc' then order by Name asc 
if @Column = Type and @Direction = 'Desc' then order by Type desc 
if @Column = Type and @Direction = 'Asc' then order by Type asc 

我的表稱爲汽車。

它有三列:CarId,名稱,類型

我試圖做到這一點,但它不返回正確的結果(彷彿被忽略順序)

select * from Cars 
order by   
case 
when @SortColumn = 'Type' and @SortDir = 'Desc' then 1 
when @SortColumn = 'Type' and @SortDir = 'Desc' then 1 
when @SortColumn = 'Name' and @SortDir = 'Asc' then 3 
when @SortColumn = 'Name' and @SortDir = 'Asc' then 3, end asc 

回答

1

CASE是表達式產生一個單一的值。它不能像您在其他語言中那樣用於流量控制,或者您可以嘗試使用IF。查詢中也不能使用IF

以下分別對待每個條件。如果條件不匹配,則該表達式的結果爲NULL,在任何排序中都將忽略該結果。因此,這些條款的順序是無關緊要的,因爲只有在所有條件都滿足將所觀察到的:

ORDER BY 
    CASE WHEN @SortColumn = 'Type' AND @SortDir = 'DESC' THEN Type END DESC, 
    CASE WHEN @SortColumn = 'Name' AND @SortDir = 'DESC' THEN Name END DESC, 
    CASE WHEN @SortColumn = 'Type' AND @SortDir = 'ASC' THEN Type END, 
    CASE WHEN @SortColumn = 'Name' AND @SortDir = 'ASC' THEN Name END; 

這些或許可以有所結合,但我不知道數據類型,所以這可能是最安全的。如果數據類型相同,則:

ORDER BY 
    CASE WHEN @SortDir = 'DESC' THEN 
    CASE WHEN @SortColumn = 'Type' THEN Type ELSE Name END 
    END DESC, 
    CASE WHEN @SortDir = 'ASC' THEN 
    CASE WHEN @SortColumn = 'Type' THEN Type ELSE Name END 
    END; 

你不能垮更遠,因爲你不能在一個表達式執行有條件ASCDESC。但您可以通過其他方式進行簡化,例如以下查詢將產生與上面相同的結果,即使在某些情況下,按順序將嘗試執行(比如說)ORDER BY Type DESC, Type DESC - 我不是100%確定優化程序是否簡化爲冗餘但它應該摺疊爲單一類型運算符(當需要時 - 有時這個查詢可以根據用於滿足查詢的索引產生固有的排序)。

ORDER BY 
    CASE WHEN @SortColumn = 'Type' AND @SortDir = 'DESC' THEN Type END DESC, 
    CASE WHEN @SortColumn = 'Name' AND @SortDir = 'DESC' THEN Name END DESC, 
    CASE WHEN @SortColumn = 'Type' THEN Type END, 
    CASE WHEN @SortColumn = 'Name' THEN Name END; 

......或者......

ORDER BY 
    CASE WHEN @SortDir = 'DESC' THEN 
    CASE WHEN @SortColumn = 'Type' THEN Type ELSE Name END 
    END DESC, 
    CASE WHEN @SortColumn = 'Type' THEN Type ELSE Name END; 

你也可以考慮,因爲動態SQL,如果這變得更加複雜,有大量的維護工作在這裏。

DECLARE @sql NVARCHAR(MAX); 
SET @sql = N'SELECT ... ORDER BY ' + @SortColumn + ' ' + @SortDir; 
PRINT @sql; 
-- EXEC sp_executesql @sql; 

當然,這可能引入其他問題(查詢,計劃緩存膨脹其餘的可維護性...)

1

你可以試試這個方法:

WITH ranked AS (
    SELECT 
    ... 
    rnk = ROW_NUMBER() OVER (
     ORDER BY 
     CASE @SortColumn 
      WHEN 'Type' THEN Type 
      WHEN 'Name' THEN Name 
     END 
    ) * CASE @Direction WHEN 'DESC' THEN -1 ELSE 1 END 
    FROM ... 
) 
SELECT 
    ... 
FROM ranked 
ORDER BY rnk 

ROW_NUMBER()功能在@SortColumn參數指定的列上生成排名,使用CASE表達式解析名稱(如@Aaron Bertrand's answer),並使用另一個CASE表達式將秩序乘以-1 if @Direction is 'DESC'。生成的等級列可以在主查詢的ORDER BY子句中使用,無需任何調整。

+0

哦,聰明,將不得不在博客文章中使用此選項。 +1,但它不會解析 - 不應該是第四行是'rnk = ROW_NUMBER()OVER('而不是'rnk = ROW_NUMBER('? –

+0

)謝謝,並且感謝我回到我的答案:錯別字......看起來很高的時候我把它稱爲一天 –

+0

爲什麼當鍵入然後鍵入,還有當名稱然後鍵入? – InfoLearner