2012-07-15 88 views
28

爲題指出:SQLite的ORDER BY包含數字字符串,從0開始

我有一個選擇查詢,這我在「按訂單」,其中包含數字的領域努力,事情是這樣的數字是真的字符串以0開頭,所以「order by」是這樣做的...

... 
10 
11 
12 
01 
02 
03 
... 

有什麼想法?編輯:如果我這樣做:「...... ORDER BY(field + 1)」我可以解決這個問題,因爲不知何故該字符串內部被轉換爲整數。這是一種「正式」將它轉換成C's atoi的方式嗎?

+0

過得好那結果呢?你確定這些字符串是否具有前導零或者是涉及的主要空間? – 2012-07-15 03:16:20

+0

該字符串沒有前導空格。我試圖找到一種方法來排序包含數字的字符串(1,2,3 ...,10,11,12),而不用1,10,2,3,4,5時序排序。我手動添加了前導0,我也嘗試過使用空格,但是我現在看到將列轉換爲INTEGER是首先要做的最聰明的事情。 – 2012-07-15 03:39:23

+2

但'01'應該在'10'之前排列爲字符串,因此我的好奇心。或者你是否說你在數據庫中確實有'1'而不是'01'? – 2012-07-15 03:46:46

回答

57

您可以使用CASThttp://www.sqlite.org/lang_expr.html#castexpr表達式轉換爲整數。

sqlite> CREATE TABLE T (value VARCHAR(2)); 
sqlite> INSERT INTO T (value) VALUES ('10'); 
sqlite> INSERT INTO T (value) VALUES ('11'); 
sqlite> INSERT INTO T (value) VALUES ('12');  
sqlite> INSERT INTO T (value) VALUES ('01'); 
sqlite> INSERT INTO T (value) VALUES ('02'); 
sqlite> INSERT INTO T (value) VALUES ('03'); 
sqlite> SELECT * FROM T ORDER BY CAST(value AS INTEGER); 
01 
02 
03 
10 
11 
12 
sqlite> 

如果我這樣做:「... ORDER BY(現場+ 1)」我能解決這個,因爲不知何故該字符串在內部被轉換爲整數。是「正式」將它轉換爲C的atoi嗎?

那麼這就是有趣的,雖然我不知道有多少DBMS支持這樣的操作,所以我不建議這樣做,以防萬一你需要使用不同的系統,該系統不支持它,何況你要添加一個額外的操作,這可能會影響性能,雖然你也這樣做ORDER BY (field + 0)我要去調查性能

從sqlite3的文檔採取:

轉換表達式用來向價值轉換與c相似的另一個存儲類將列親和力應用於值時發生的反轉。 CAST表達式的應用與列親和性的應用是不同的,就像CAST表達式一樣,即使存儲類轉換是有損和不可逆的,也會強制存儲類轉換。

4.0運營商
所有數學運算符(+, - ,*,/,%,< <,>>,&,和|)正在開展前投兩個操作數的數字存儲類。即使它是有損和不可逆轉的,演員也會穿過。數學運算符上的NULL操作數會產生NULL結果。數學運算符上的操作數不會以任何方式查看數字並且不爲NULL會被轉換爲0或0.0。

我是古董,所以我跑了一些基準:

>>> setup = """ 
... import sqlite3 
... import timeit 
... 
... conn = sqlite3.connect(':memory:') 
... c = conn.cursor() 
... c.execute('CREATE TABLE T (value int)') 
... for index in range(4000000, 0, -1): 
...  _ = c.execute('INSERT INTO T (value) VALUES (%i)' % index) 
... conn.commit() 
... """ 
>>> 
>>> cast_conv = "result = c.execute('SELECT * FROM T ORDER BY CAST(value AS INTEGER)')" 
>>> cast_affinity = "result = c.execute('SELECT * FROM T ORDER BY (value + 0)')" 
>>> timeit.Timer(cast_conv, setup).timeit(number = 1) 
18.145697116851807 
>>> timeit.Timer(cast_affinity, setup).timeit(number = 1) 
18.259973049163818 
>>> 

正如我們可以看到它的慢一點,雖然不是很大,有意思。

+0

+1謝謝你的小實驗 – 2012-07-15 03:17:03

+1

どういたしまして,沒問題,更新了我的答案。 – 2012-07-15 04:00:41

+0

感謝您的基準!也許+0操作數在被執行之前會被優化掉,如果是這樣的話,+1或者+隨機肯定會導致更慢的查詢。 – 2012-07-18 03:35:20

24

你可以使用CAST

ORDER BY CAST(columnname AS INTEGER) 
+0

這是正確的格式ORDER BY CAST(columnname AS INTEGER)= '01' – sherin 2014-03-19 05:51:20

+0

我們有一個贏家 - 謝謝! – Rob 2015-11-26 01:29:57

2

在光標加載器ListView中!

String projection= some string column; 
String selection= need to select; 

String sort="CAST ("+ YOUR_COLUMN_NAME + " AS INTEGER)"; 

CursorLoader(getActivity(), Table.CONTENT_URI, projection, selection, selectionArgs, sort); 
0

感謝Skinnynerd。與Kotlin,CAST的合作如下: CAST解決了優先考慮超過10個或超過206個問題的問題。

定義全局變量以後需求改變,然後在查詢中插:

var SortOrder:String?=null 

改變順序使用:

對於後代:

SortOrder = "CAST(MyNumber AS INTEGER)" + " DESC" 

(從從最高到最低)

對於升序:

SortOrder = "CAST(MyNumber AS INTEGER)" + " ASC" 

(從最低到最高)