2016-08-03 108 views
1

我有一個SQL語句如下:SQL服務器:ORDER BY參數報表

SELECT A.ID, A.Name 
FROM Properties A 
WHERE A.ID IN (110, 105, 104, 106) 

當我運行該SQL語句時,輸出根據IN列表中ID自動返回有序

104 West 
    105 East 
    106 North 
    110 South 

我想知道是否有可能按順序排列參數在IN子句中列出。所以它會返回

110 South 
105 East 
104 West 
106 North 
+0

不,這是不可能的。 –

+0

由於它們看起來是隨機排列的,所以不需要訂購。 IN沒有訂購。 – Missy

+1

所以你想訂購它沒有特別的順序...很酷。 –

回答

4

當然...

只是添加一個ORDER子句的情況下,它

SELECT A.ID, A.Name 
FROM Properties A 
WHERE A.ID IN (110,105,104,106) 
Order By case A.ID 
    when 110 then 0 
    when 105 then 1 
    when 104 then 2 
    when 106 then 3 end 
+0

對這些值進行硬編碼將不起作用 - 當下一個字符串傳入時會發生什麼它是'112,47,108,96'? –

10

我認爲在SQL Server中最簡單的方法是使用一個JOINVALUES

SELECT p.ID, p.Name 
FROM Properties p JOIN 
    (VALUES (110, 1), (105, 2), (104, 3), (106, 4)) ids(id, ordering) 
    ON p.id = a.id 
ORDER BY ids.ordering; 
+0

哈哈...我從來沒有料到這個問題會觸發這麼多的答案!但都很有趣 – techspider

+1

如果OP可以更改查詢*和*應用程序(按順序傳遞),則這將起作用。如果OP無法更改應用程序以順序傳遞,那麼UDF解決方案會更好地工作。 –

4

藉助解析函數,它返回序列以及

SELECT B.Key_PS 
    , A.ID 
    , A.Name 
FROM Properties A 
Join (Select * from [dbo].[udf-Str-Parse]('110,105,104,106',',')) B on A.ID=B.Key_Value 
WHERE A.ID IN (110,105,104,106) 
Order by Key_PS 

的UDF,如果你需要

CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimeter varchar(10)) 
--Usage: Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',') 
--  Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ') 
--  Select * from [dbo].[udf-Str-Parse]('id26,id46|id658,id967','|') 
--  Select * from [dbo].[udf-Str-Parse]('hello world. It. is. . raining.today','.') 

Returns @ReturnTable Table (Key_PS int IDENTITY(1,1), Key_Value varchar(max)) 
As 
Begin 
    Declare @XML xml;Set @XML = Cast('<x>' + Replace(@String,@Delimeter,'</x><x>')+'</x>' as XML) 
    Insert Into @ReturnTable Select Key_Value = ltrim(rtrim(String.value('.', 'varchar(max)'))) FROM @XML.nodes('x') as T(String) 
    Return 
End 

解析器單獨將返回

Select * from [dbo].[udf-Str-Parse]('110,105,104,106',',') 

Key_PS Key_Value 
1  110 
2  105 
3  104 
4  106 
0

這裏是一個不依賴於硬編碼值或動態SQL的解決方案(以消除硬編碼值)。

我會用OrderByValue和OrderBySort構建一個表(可能是temp或變量),並從應用程序插入。

OrderByValue OrderBySort 
110   1 
105   2 
104   3 
106   4 

然後,我會加入的價值和排序的排序。連接將與In子句相同。

SELECT A.ID, A.Name 
    FROM Properties A 
    JOIN TempTable B On A.ID = B.OrderByValue 
    Order By B.OrderBySort 
3

什麼你可能做的是:

  1. 創建一個TVF,將拆分字符串,並保持原來的順序。

這個問題似乎有這個功能已經寫:MS SQL: Select from a split string and retain the original order記住,可能還有其他的辦法,不僅那些覆蓋在這個問題上,我只是把它作爲一個例子來了解哪些功能應做

所以,現在如果你想運行此查詢:

SELECT * 
FROM dbo.Split('110,105,104,106', ',') AS T; 

這將帶回本表結果。

items rownum 
------------ 
110 1 
105 2 
104 3 
106 4 

在此之後,你可以簡單地查詢你的表,加入這個TVF通過你的ID作爲一個參數:

SELECT P.ID, P.Name 
FROM Properties AS P 
INNER JOIN dbo.Split('110,105,104,106', ',') AS T 
    ON T.items = P.ID 
ORDER BY T.rownum; 

這應該保留的參數順序。

如果您需要更好的性能,我建議將來自TVF的記錄放入哈希表中,索引它,然後與實際表進行連接。請參閱下面的查詢:

SELECT T.items AS ID, T.rownum AS SortOrder 
INTO #Temporary 
FROM dbo.Split('110,105,104,106', ',') AS T; 

CREATE CLUSTERED INDEX idx_Temporary_ID 
    ON #Temporary(ID); 

SELECT P.ID, P.Name 
FROM Properties AS P 
INNER JOIN #Temporary AS T 
    ON T.ID = P.ID 
ORDER BY T.SortOrder; 

這應該在更大的數據集上工作得更好,對小的數據集也應該更好。

0

此問題的另一個解決方案是按照上款準備一個臨時表像

declare @InTable table (ID int, SortOrder int not null identity(1,1)); 

我們可以爲了填充這個臨時表與您的數據,你想

insert into @InTable values (110), (105), (104), (106); 

最後,我們需要修改您的問題使用這個臨時表像這樣

select A.ID, A.Name 
from Properties A 
inner join @InTable as Sort on A.ID = Sort.ID 
order by Sort.SortOrder 

在輸出,你可以看到噸他的

ID Name 
110 South 
105 East 
104 West 
106 North 

在此解決方案中,您不需要以特殊方式提供訂單。您只需按照需要插入值。