2010-07-24 19 views
2

我有字母標記列表,說'1a', '1b', '02', '03', '10', '11',等等T-SQL - 順序按字母上

現在,什麼是被標記的這個名單上做一個順序的最佳方式?

我越來越'1a', '1b', '10', '11', '02', '03',

,但我需要它是

'1a', '1b', '02', '03', '10', '11' 

UPDATE

好吧,我建議以後這樣做,但它不工作。

declare @tokens table(token varchar(20)); 

insert into @tokens 
select '1a' 
select '1b' 
select '02' 
select '10' 

select * from @tokens 
order by case 
when ISNUMERIC(token) = 1 then right('0000000000'+token+'0',10) 
else right('0000000000'+token,10) 
end 

我收到響應,'1b', '02', '10', '1a'

UPDATE2

它的工作原理進行以下更改後。

declare @tokens table(token varchar(20)); 

insert into @tokens 
select '1a' 
insert into @tokens 
select '1b' 
insert into @tokens 
select '02' 
insert into @tokens 
select '10' 


select token from @tokens 
order by case 
when ISNUMERIC(token) = 1 then right('0000000000'+token+'0',10) 
else right('0000000000'+token,10) 
end 

感謝所有的你的美好想法。

+0

您使用的數據庫是? – Oded 2010-07-24 18:41:48

+0

@Oded - sql server 2008,更正了標題,謝謝。 – SoftwareGeek 2010-07-24 18:42:28

+0

@SoftwareGeek - 出於好奇,數據代表什麼?字母字符是否有特殊含義? – Thomas 2010-07-24 19:27:51

回答

8

的最簡單的解決方案是預先掛起零

Select ... 
From Table 
Order By Right('0000000000' + YourColumn, 10) 

然而,這將不考慮字母字符。爲了處理字母字符,你需要知道你可能有多少個潛在的字母字符。如果有一個,你可以這樣做:

Select ... 
From #Test 
Order By Case 
    When IsNumeric(NumVal) = 1 Then Right('0000000000' + NumVal + '0', 10) 
    Else Right('0000000000' + NumVal, 10) 
    End 

加成

試運行:

If object_id('tempdb..#Test') is not null 
    Drop Table #Test 

Create Table #Test (NumVal varchar(10)) 
Insert #Test(NumVal) Values('02') 
Insert #Test(NumVal) Values('03') 
Insert #Test(NumVal) Values('1a') 
Insert #Test(NumVal) Values('1b') 
Insert #Test(NumVal) Values('10') 
Insert #Test(NumVal) Values('11') 

Select NumVal 
From #Test 
Order By Case 
    When IsNumeric(NumVal) = 1 Then Right('0000000000' + NumVal + '0', 10) 
    Else Right('0000000000' + NumVal, 10) 
    End 

Results: 
1a 
1b 
02 
03 
10 
11 

的說明一下我的解決方案。如果字母符號具有特殊含義,那麼Erick Robertson建議您應該將數據分成不同的列。上述解決方案將只處理兩個非常特殊的情況:一個全數值,一個帶有單個尾隨字母字符的值。如果數據可能具有多個字母字符,或者字母字符有時位於值的結尾以外,我的解決方案將無法工作。另外,應該指出的是,我的解決方案將導致表掃描來評估每個值的可排序字符串。

如果您尋求的是一次性快速解決方案,那麼我的方法就會奏效。如果您正在尋求一個長期解決方案,那麼將數據拆分爲單獨的列,接受愚蠢的排序順序或添加一個指定每個值的相對排序順序的列。

+0

爲什麼不把'0000000002'放在'000000001a'之前? – 2010-07-24 18:48:07

+0

@Erick Robertson - 修改了我的帖子。沒有機會第一次充實這一切。 – Thomas 2010-07-24 18:51:47

+0

這看起來似乎不再是最簡單的解決方案。 :) – 2010-07-24 18:55:40

1

最好的解決方案是有一個單獨的字段,它存儲令牌的int值。維護令牌列時應維護此列。然後,在排序時,按int值列和令牌列排序。這將允許您對這些列進行索引,以便快速檢索具有大型數據集的數據。

從alpha到int的轉換函數很慢,無法利用索引來加快查詢速度。隨着數據集的增長,這種類型的解決方案將只會變得越來越慢,並使數據庫停滯不前。

+0

恭敬地,我不得不不同意。有一個更好的方法。我喜歡這裏的解決方案,它的工作原理。或者,我也會和@ Rob的建議一起走。 – SoftwareGeek 2010-07-24 20:53:48

+0

@SoftwareGeek - 最好的方法是使用數據庫索引。當然,如果您無法修改數據庫,那麼最好的解決方案就不存在了。數據庫的設計者應該已經意識到人們會希望通過這種方法獲取數據並進行相應的設計。 – 2010-07-24 22:25:23

2

如果您熟悉C#或VB.net,則可能需要考慮編寫一個CLR函數來執行排序,因爲此排序順序不夠標準,難以全面正確地描述TSQL。

+0

是的,v.good建議,但如果db可以執行任務,那麼我讓它處理它。 – SoftwareGeek 2010-07-24 20:51:33

+0

@SoftwareGeek,我明白你的意思了,但是,...... CLR函數與TSQL的性能明顯相比「非常好」,並且擁有另一種工具可用,尤其是一種更適合於給定任務=) – Rob 2010-07-25 13:04:49