Sql-Server
將沒有列的 ROW_NUMBER() 添加到 ORDER BY?
所以我正在研究一個程式碼高爾夫拼圖,需要在結果中添加一個 INT“數字”列n,同時保持目前順序。
假設我的源數據是:
SELECT value FROM STRING_SPLIT('one,two,three,four,five', ',')
它以原始(所需)順序返回項目:
value ----- one two three four five
如果我嘗試使用
ROW_NUMBER()
或者RANK()
我被迫指定一個ORDER BY
,這value
是唯一合法的選擇:SELECT value, n = ROW_NUMBER() OVER(ORDER BY value) FROM STRING_SPLIT('one,two,three,four,five',',')
但這(如預期的那樣)按
value
字母順序排序,而不是按所需的原始順序排列:value n ------ --- five 1 four 2 one 3 three 4 two 5
加入數字表是行不通的,因為沒有
WHERE
子句我會得到一個完整的外連接。我能想到的最好的方法是使用帶有標識欄位的臨時表:
CREATE TABLE #argg (n INT IDENTITY(1,1), v VARCHAR(99)) INSERT #argg SELECT value v FROM STRING_SPLIT('one,two,three,four,five',',') SELECT * FROM #argg DROP TABLE #argg
但這真的很長而且很煩人。有更好的想法嗎?
執行此操作的規範方法如下
ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
:如果你在打高爾夫球,你可以嘗試這樣的事情:SELECT value, n = ROW_NUMBER() OVER(ORDER BY (SELECT 1)) FROM STRING_SPLIT('one,two,three,four,five',',')
它適用於您在問題中發布的簡單案例:
我應該說,沒有文件保證該
ROW_NUMBER()
值將按照您期望的精確順序。但這是程式碼高爾夫,所以這似乎已經足夠好了。
您不能依賴您
INSERT
按原始字元串的順序生成IDENTITY
值。這可能是你觀察到的,但這只是幸運的巧合,當然不能保證。如果您沒有重複項,以下將起作用:
DECLARE @str varchar(255) = 'one,two,three,four,five'; SELECT value, n = ROW_NUMBER() OVER (ORDER BY CHARINDEX(',' + value + ',', ',' + @str + ',')) FROM STRING_SPLIT('one,two,three,four,five', ',') ORDER BY n;
對於程式碼高爾夫也許:
DECLARE @s char(99)='one,two,three,four,five'; SELECT value,n=RANK() OVER(ORDER BY CHARINDEX(','+value+',',','+@s+',')) FROM STRING_SPLIT('one,two,three,four,five', ',')ORDER BY n
如果你有重複,它變得更加複雜。這裡的一些想法可能是: