非标准排序顺序

时间:2012-11-18 23:53:42

标签: sql ruby-on-rails ruby

我在SQL列中有以下数据。列类型是String。当我从数据库中查询数据时,我更愿意对这些数据进行排序,但我想在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

3 个答案:

答案 0 :(得分: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

去哪个跑得更快。

答案 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

对于其他数据库,您可以使用正则表达式匹配而不是isnumeric来确定哪些是数字。

由于您使用的是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美元/月”被视为一个数字。你可以使用regexp解决这个问题,如果你有的话。或者,如果“/”定义了这些情况,您可以使用以下特定内容:

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

答案 2 :(得分:0)

如果现有的答案在SQLlite中有效,那么它们可能适合您。因为数据非常......凌乱......我倾向于尝试将这个丑陋的部分封装在一个返回排序数组的方法中。

如果你有这么少的行(例如少于500行),那么更简洁的排序方法是包括Comparable并编写一个自定义比较器,如nicely documented in this SO answer