Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何按照用户的期望对字母和数字的混合列表进行排序和显示?_Sql_Database_Alphanumeric_Natural Sort - Fatal编程技术网

Sql 如何按照用户的期望对字母和数字的混合列表进行排序和显示?

Sql 如何按照用户的期望对字母和数字的混合列表进行排序和显示?,sql,database,alphanumeric,natural-sort,Sql,Database,Alphanumeric,Natural Sort,我们的应用程序有一个CustomerNumber字段。我们有数百名不同的用户使用该系统(每个人都有自己的登录名和自己的CustomerNumbers列表)。单个用户最多可能有100000个客户。许多人的收入不到100英镑 有些人只在他们的客户编号字段中输入实际数字,而其他人则混合使用。系统允许20个字符,可以是A-Z、0-9或破折号,并将这些字符存储在VARCHAR2(20)中。任何小写字母在存储之前都会变成大写 现在,假设我们有一个简单的报告,其中列出了特定用户的所有客户,并按客户编号排序。e

我们的应用程序有一个
CustomerNumber
字段。我们有数百名不同的用户使用该系统(每个人都有自己的登录名和自己的
CustomerNumber
s列表)。单个用户最多可能有100000个客户。许多人的收入不到100英镑

有些人只在他们的客户编号字段中输入实际数字,而其他人则混合使用。系统允许20个字符,可以是A-Z、0-9或破折号,并将这些字符存储在VARCHAR2(20)中。任何小写字母在存储之前都会变成大写

现在,假设我们有一个简单的报告,其中列出了特定用户的所有客户,并按客户编号排序。e、 g

SELECT CustomerNumber,CustomerName
FROM Customer
WHERE User = ?
ORDER BY CustomerNumber;
这是一个天真的解决方案,因为那些只使用数字的人不希望看到简单的字母排序(其中“10”在“9”之前)

我不希望向用户询问有关其数据的任何不必要的问题

我正在使用Oracle,但我认为看到其他数据库的一些解决方案会很有趣。请包括您的答案使用的数据库


您认为实现这一点的最佳方法是什么?

您最好的选择可能是预先计算一个单独的列,并使用该列进行订购,并使用客户编号进行显示。这可能涉及将任何内部整数填充到固定长度

另一种可能是对返回的结果进行排序后选择

关于一些人如何计算人性化排序顺序的帖子。

在Oracle 10g中:

SELECT  cust_name
FROM    t_customer c 
ORDER BY
    REGEXP_REPLACE(cust_name, '[0-9]', ''), TO_NUMBER(REGEXP_SUBSTR(cust_name, '[0-9]+'))
这将按照数字的第一次出现进行排序,而不考虑其位置,即。e、 :

  • customer1
    • cust1omer?客户1
    • customer1?客户2
  • ,其中,
    表示订单未定义

    这在大多数情况下就足够了

    要强制对案例
    2
    进行排序,您可以将
    REGEXP_INSTR(客户名称,[0-9]',n)
    添加到
    列表
    n
    次排序,强制在
    n
    -th(
    2nd
    3rd
    等)数字组第一次出现时进行排序

    要强制对案例
    3
    排序,您可以将
    添加到\u编号(REGEXP\u SUBSTR(客户名称,[0-9]+',n))
    按次排序,强制顺序为
    n
    -th。一组数字

    实际上,我写的查询已经足够了


    您可以根据这些表达式创建基于函数的索引,但需要使用提示强制执行,并且会执行一次通过的排序方式,因为
    CBO
    对函数基索引的信任程度不足以允许对它们执行排序方式。

    您可以有一个数字列[CustomerNumber]仅当CustomerNumber为纯数字(否则为空[1])时才使用,然后


    [1] 根据您的SQL版本按顺序处理空值的方式,您可能希望将其默认为零(或无限!)

    我遇到了类似的可怕情况,并开发了一个适当的可怕函数来处理它(SQLServer)

    在我的情况下,我有一个“单位”表(这是一个学生的工作跟踪系统,所以这里的单位代表他们正在学习的课程)。单元有一个代码,大部分代码都是纯数字的,但出于各种原因,它被做成了一个varchar,它们决定在一些单元前加上最多5个字符的前缀。因此,他们预计53123237356会正常排序,但T53、T123、T237、T356也会正常排序

    UnitCode是一个nvarchar(30)

    以下是函数的主体:

    declare @sortkey nvarchar(30)
    
    select @sortkey = 
        case
            when @unitcode like '[^0-9][0-9]%' then left(@unitcode,1) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-1)
            when @unitcode like '[^0-9][^0-9][0-9]%' then left(@unitcode,2) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-2)
            when @unitcode like '[^0-9][^0-9][^0-9][0-9]%' then left(@unitcode,3) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-3)
            when @unitcode like '[^0-9][^0-9][^0-9][^0-9][0-9]%' then left(@unitcode,4) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-4)
            when @unitcode like '[^0-9][^0-9][^0-9][^0-9][^0-9][0-9]%' then left(@unitcode,5) + left('000000000000000000000000000000',30-(len(@unitcode))) + right(@unitcode,len(@unitcode)-5)
            when @unitcode like '%[^0-9]%' then @unitcode
            else left('000000000000000000000000000000',30-len(@unitcode)) + @unitcode
        end 
    
    return @sortkey
    

    写了这篇文章后,我想打自己的脸,但它确实有效,而且似乎不会在服务器运行时杀死服务器。

    我在SQL server中使用了这一点,效果很好:这里的解决方案是在数字值的前面加上一个字符,这样所有的字符串长度都相同

    以下是使用该方法的示例:

    select MyCol
    from MyTable
    order by 
        case IsNumeric(MyCol) 
            when 1 then Replicate('0', 100 - Len(MyCol)) + MyCol
            else MyCol
        end
    
    100应该替换为该列的实际长度。

    另请参见,以及其他标记为“自然排序”的内容,以便讨论和实现。。。
    select MyCol
    from MyTable
    order by 
        case IsNumeric(MyCol) 
            when 1 then Replicate('0', 100 - Len(MyCol)) + MyCol
            else MyCol
        end