如何在按字母顺序包含数字的varchar字段上进行排序?

时间:2010-01-12 20:28:37

标签: sql sql-server

我确信这一定是一个非常常见的问题所以我猜微软已经解决了这个问题。我的谷歌搜索技能只是没有达到标准。我有一个我想订购的字段,它是一个varchar字段,例如

  • Q
  • Num 10
  • Num 1
  • A
  • Num 9
  • Num 2
  • ˚F

现在我希望结果是

  • A
  • ˚F
  • Num 1
  • Num 2
  • Num 9
  • Num 10
  • Q

但事实并非如此。它如下(注意Num 10是在Num 1之后,而不是按预期的Num 9)

  • A
  • ˚F
  • Num 1
  • Num 10
  • Num 2
  • Num 9
  • Q

现在我知道这个的原因所以你不需要解释:)但我不记得如何解决它,或者是否有一个好的标志或命令,我可以使用它来正确。

编辑:

上面的例子只是一个例子。该列可以包含任何值。字母和数字的任意组合。有没有办法按字母顺序按字母顺序排序,而不是按字母顺序对ASCII值进行排序?

编辑2: 谢谢你到目前为止的答案。我在谈论任何仲裁数据。如果它处于固定位置或之前的某些东西那么它很容易,我不会问。我要求用任何仲裁数据来解决这个问题的一般方法。不是模式,没有规则,没有任何规则。

4 个答案:

答案 0 :(得分:1)

如果该字段的末尾始终有一个数字,前面可能有一个单词,并且前面有一个空格,则可以使用CHARINDEX / SUBSTRING来解决此问题。

以下是一个例子:

select *
from (
    select 'Q' x
    union
    select 'Num 10'
    union
    select 'Num 1'
    union
    select 'A'
    union
    select 'Num 9'
    union
    select 'Num 2'
    union
    select 'F'
) a
order by
    case
        when CHARINDEX(' ', x) <> 0 then LEFT(x, CHARINDEX(' ', x) - 1)
        else x
    end,
    cast(case
        when CHARINDEX(' ', x) <> 0 then substring(x, CHARINDEX(' ', x) + 1, LEN(x) - CHARINDEX(' ', x) )
        else ''
    end as int)

这个输出是:

A
F
Num 1
Num 2
Num 9
Num 10
Q

修改

由于您的数据不够稳定,无法使用硬编码方法,因此该解决方案需要采取更为激烈的措施。我已经尝试过基于T-SQL的函数,这些函数将提供一种自然排序形式,但发现它们太慢而无法使用。相反,我写了一个基于CLR的函数,它表现得非常好。该函数返回可以排序的标量值。您可以在over here找到代码和安装说明。

答案 1 :(得分:1)

这是Ascii排序与自然排序的古老问题

有关详细信息,请参阅Sorting for Humans : Natural Sort Order

答案 2 :(得分:1)

你添加了

  

该列可以包含任何值。字母和数字的任意组合

那么,你想在哪里以“foo1bar”和“foo10bar”为例?还是“foo10bar11”和“foo10bar1”?还是“Foo Two”和“Foo Three”?

没有明智的数据,没有明智的解决方案。你有随机数据。定义“人类可读”。

答案 3 :(得分:1)

  

“我要求一般解决方案   任何仲裁数据都存在这个问题。   不是模式,没有规则,没有任何东西。“

问题是,编程就是要找到模式,从模式中导出规则并根据这些规则应用解决方案。所以没有这些先决条件,你的问题就很难了。

基本上,您需要做的是将排序字符串标记为纯字母和纯数字块,并对每个类别应用不同的排序顺序。只要你有某种模式,这是可行的。

   AAA999AA
   A9AAAAA
   A999A

但是每个模式需要一个定制的解决方案。任意数据排列的一般解决方案都是一个很大的问题。