【问题标题】:ORDER BY varchar with [a-9] instead of [0-Z] in SQLORDER BY varchar 使用 [a-9] 而不是 SQL 中的 [0-Z]
【发布时间】:2012-04-10 00:18:56
【问题描述】:

默认情况下,SQL 将数字排在字符之前。

所以如果我有“名称”列:

abc
ab1
a1b
1ba
1bac
b21

由于 SQL 按 0-Z 排序(先从 0 到 9,然后是 a-Z),因此查询

SELECT * FROM ... ORDER BY name

将导致:

1ba
1bac
a1b
ab1
abc
abc1
b21

但我希望它按 a-0 排序(首先是 a-Z,然后是 0-9)。

abc
abc1
ab1
a1b
b21
1ba
1bac

如何在查询中执行此操作?更具体地说,如何在 SQLite 中执行此操作?

我在 Sort MySQL results alphabetically, but with numbers last 中找到了一个解决方案,但仅限于第一个字符。

【问题讨论】:

标签: sql sqlite sql-order-by


【解决方案1】:

使用提供的数据可以解决问题。

SELECT *
FROM Table
ORDER BY Name COLLATE SQL_EBCDIC037_CP1_CS_AS

但是,您可能需要查看各种排序规则类型,以确保它全面满足您的需求。

更新:您提到了 SQLite,但我在 MSSQL 上对此进行了测试。不确定此排序规则在 SQLite 中是否可用,但下面的 cmets 可能有有用的信息。

【讨论】:

  • OP 实际上提到了 SQLite,但这可能会奏效 - 我不知道 SQLite 中是否存在可以解决问题的现有排序规则序列,但是 - 可能必须创建一个。
  • 正如@DavidFaber 指出的那样,实际的目标平台是SQLite。我找到了sqlite.org/datatype3.html 但我真的不明白这个解决方案在 SQLite 中是否可行。
【解决方案2】:

我建议 SELECT 输入另一列,例如 name_replace,将数字替换为高位 ASCII 字符(例如 ~),然后按该列排序,然后按名称排序。不幸的是,SQLite 不支持 regular expression 替换:

SELECT name, replace( ... replace(replace(name, '0', '~'), '1', '~') ... '9', '~') AS name_replace
  FROM mytable
 ORDER BY name_replace, name

name_replace 上排序时,数字将排在最后。在name 上排序,然后将按数字排序。

【讨论】:

    【解决方案3】:

    这是我的想法:添加另一个“help_column”,检查第一个字符是否为数字并将其分配 1,否则分配 0,然后按此列排序,然后按名称排序:

    select *, case
                 when substring(name,1,1) like '[0-9]' then 1 
                 else 0 
              end as help_order
    from (
    select 'ab1' as name union select 'a1b' as name union select '1ba' as name union select 'b21' as name
    ) a
    order by help_order, name
    

    当然,如果需要,您可能需要改进正则表达式 [0-9] 以处理多个数字。

    当然,您应该替换内部查询(与您的表有多个联合的查询)。

    【讨论】:

    • 这仅适用于第一个字符(我在第一次尝试时犯了同样的错误)
    【解决方案4】:

    请用这些数据进行测试

    declare @t table(a char(3))
    insert @t values('ab1')
    insert @t values('a1b')
    insert @t values('1ba')
    insert @t values('b21')
    insert @t values('12a')
    insert @t values('13b')
    
    
    select a,
    patindex('[0-9]%', a + 'a'), 
    patindex('_[0-9]%', a + 'a'), 
    patindex('__[0-9]%', a + 'a')
    from @t order by 2, 3, 4, 1
    

    select a
    from 
    (select a,
    patindex('[0-9]%', a + 'a') b, 
    patindex('_[0-9]%', a + 'a') c, 
    patindex('__[0-9]%', a + 'a') d
    from @t) e
    order by b, c, d, a
    

    【讨论】:

    • 我不相信这是有效的 SQLite 语法。
    【解决方案5】:

    Thsi 将 0-9 替换为 ASCII 122(小写 z)以上。

    SQLLite 没有 CHAR 函数来进行字符代码替换(例如 CHAR(123)CHAR(132)),这可能需要代替我的 CHAR(123) 尝试

    当然未经测试:-)

    ORDER BY
       REPLACE
       REPLACE(
       REPLACE(
       REPLACE(
       REPLACE(
       REPLACE(
       REPLACE(
       REPLACE(
       REPLACE(
       REPLACE(name, '0', '{0')
        , '1', '{2')
        , '2', '{2')
        , '3', '{3')
        , '4', '{4')
        , '5', '{5')
        , '6', '{6')
        , '7', '{7')
        , '8', '{8')
        , '9', '{9')
    

    编辑:虽然,@David Faber 的解决方案做同样的事情,但更简单...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多