2012-11-18 80 views
0

我在SQL列中有以下數據。列類型是字符串。當我從數據庫中查詢數據時,我更願意對這些數據進行排序,但是我認爲在SQL查詢完成後可以用一些Ruby魔術來組織它。還有其他列被拔出,所以這只是需要排序的列之一。非標準排序順序

Expenses 
$3500/MONTH 
$1,000.00 
STANDARD CONTRACTOR 
$5,000.00 

數據不能改變,必須存儲在同一列(上面的例子只是測試數據)。

我想通過增加數字,然後剩下的(字符串)值來組織數據。預期的結果應該是:

$1,000.00 
$5,000.00 
$3500/MONTH 
STANDARD CONTRACTOR 

$1,000.00 
$5,000.00 
STANDARD CONTRACTOR 
$3500/MONTH 
+1

您使用的數據庫是? –

+0

我認爲你正在尋找一種「自然排序」。如果是這樣[已經完成](http://stackoverflow.com/q/34518/2509)。 – dmckee

+0

@戈登數據庫是SQLITE3。 –

回答

1

選項1(fiddle here)

select expenses from table1 
order by 
    replace(replace(expenses, "$", ""), ",", "") regexp "[0-9.]*" desc, 
    case when replace(replace(expenses, "$", ""), ",", "") regexp "[0-9.]*" 
    then cast(replace(replace(expenses, "$", ""), ",", "") as real) 
    else 0 
    end 

選項2(fiddle here):

select expenses from (
    select expenses, 
     replace(replace(expenses, "$", ""), ",", "") expensesNormalized 
    from table1 
) s 
order by 
    expensesNormalized regexp "[0-9.]*" desc, 
    case when expensesNormalized regexp "[0-9.]*" 
    then cast(expensesNormalized as real) 
    else 0 
    end 

以更快的速度運行。

+0

我最終使用了選項1,但必須略微按摩該答案以使其適用於我的特定(實際)數據。 +1爲我帶來了正確的方向和小提琴的例子。 –

0

在SQL Server中,你可以做類似如下:

order by (case when isnumeric(col) = 1 then 1 else 0 end) desc, 
     (case when isnumeric(col) = 1 then cast(col as money) end), 
     col 

對於其他數據庫,你可以使用正則表達式匹配而不是用數字來確定哪些是數字。

由於您使用SQLite和我似乎能夠承擔所有的數字與一個「$」開頭,那麼這樣的事情幾乎工程:

order by (case when substr(col, 1, 1) = '$' then 1 else 0 end) desc, 
     (case when substr(col, 1, 1) = '$' then cast(col as numeric) end), 
     col 

的問題是,「$ 3,500名/月「被視爲一個數字。你可以用一個正則表達式來解決這個問題,如果你有這個問題的話。或者,如果 「/」 定義這些情況下,您可以使用特定的喜歡的東西:

order by (case when substr(col, 1, 1) = '$' and col not like '%/%' then 1 else 0 end) desc, 
     (case when substr(col, 1, 1) = '$' and col not like '%/%' then cast(col as numeric) end), 
     col 
0

如果現有答案在SQLlite中有效,那麼他們可能會爲你工作。因爲數據非常...雜亂......我傾向於嘗試在返回排序數組的單個方法中封裝這個醜陋的部分。

如果你有少量這樣的行(例如小於500),那麼更簡潔的排序方式是包含Comparable並寫入自定義比較器,如nicely documented in this SO answer