代码之家  ›  专栏  ›  技术社区  ›  SoftwareGeek

T-Sql-按字母数字排序

  •  2
  • SoftwareGeek  · 技术社区  · 15 年前

    我有一个字母数字标记的列表,比如 '1a', '1b', '02', '03', '10', '11', 等。。。

    我要走了 '1a', '1b', '10', '11', '02', '03',

    但我需要它

    '1a', '1b', '02', '03', '10', '11' 
    

    好的,我是在建议之后做的,但是不起作用。

    declare @tokens table(token varchar(20));
    
    insert into @tokens
    select '1a'
    select '1b'
    select '02'
    select '10'
    
    select * from @tokens
    order by case
     when ISNUMERIC(token) = 1 then right('0000000000'+token+'0',10)
     else right('0000000000'+token,10)
     end
    

    我得到的答复是 '1b', '02', '10', '1a'

    更新2

    在进行以下更改之后,它就可以工作了。

    declare @tokens table(token varchar(20));
    
    insert into @tokens
    select '1a'
    insert into @tokens
    select '1b'
    insert into @tokens
    select '02'
    insert into @tokens
    select '10'
    
    
    select token from @tokens
    order by case
     when ISNUMERIC(token) = 1 then right('0000000000'+token+'0',10)
     else right('0000000000'+token,10)
     end
    

    3 回复  |  直到 15 年前
        1
  •  9
  •   Thomas    15 年前

    最简单的解决方案是预先挂起零

    Select ...
    From Table
    Order By Right( '0000000000' + YourColumn, 10)
    

    但是,这不会考虑字母字符。为了处理alpha字符,你需要知道你可能有多少潜在的alpha字符。如果有,你可以这样做:

    Select ...
    From #Test
    Order By Case
        When IsNumeric(NumVal) = 1 Then Right('0000000000' + NumVal + '0', 10)
        Else Right('0000000000' + NumVal, 10)
        End
    

    加法

    试运行:

    If object_id('tempdb..#Test') is not null
        Drop Table #Test
    
    Create Table #Test ( NumVal varchar(10) )
    Insert #Test(NumVal) Values('02')
    Insert #Test(NumVal) Values('03')
    Insert #Test(NumVal) Values('1a')
    Insert #Test(NumVal) Values('1b')
    Insert #Test(NumVal) Values('10')
    Insert #Test(NumVal) Values('11')
    
    Select NumVal
    From #Test
    Order By Case
        When IsNumeric(NumVal) = 1 Then Right('0000000000' + NumVal + '0', 10)
        Else Right('0000000000' + NumVal, 10)
        End
    
    Results:
    1a
    1b
    02
    03
    10
    11
    

    关于我的解决方案的说明。如果字母字符有特殊的含义,那么正如Erick Robertson所建议的那样,您应该将数据分解为单独的列。上面的解决方案只处理两种非常特殊的情况:一种是全数字值,另一种是带有单个尾随字母字符的值。如果数据可能有多个字母字符,或者字母字符有时不在值的末尾,那么我的解决方案将不起作用。此外,应该注意的是,我的解决方案将导致表扫描来计算每个值上的可排序字符串。

    如果你所寻求的是一次性的快速解决方案,那么我的方法就会奏效。如果您正在寻找一个长期的解决方案,那么要么将数据分解为单独的列,接受愚蠢的排序顺序,要么添加一个列来指定每个值的相对排序顺序。

        2
  •  2
  •   Rob    15 年前

    如果您熟悉C#或VB.net,可能值得考虑编写一个CLR函数来为您执行排序,因为这种排序顺序不够标准,很难在TSQL中全面、正确地描述。

        3
  •  1
  •   Erick Robertson    15 年前

    最好的解决方案是有一个单独的字段来存储令牌的int值。在维护token列时,应该维护此列。然后在排序时,先按int value列排序,然后按token列排序。这将允许您为这些列编制索引,以便使用大型数据集快速检索数据。

    从alpha到int的转换函数很慢,不能利用索引来加速查询。随着数据集的增长,这种类型的解决方案只会变得更慢,使数据库陷入困境。