2012-11-18 73 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