如何按照用户的期望排序和显示字母和数字的混合列表?
我们的应用程序有一个 CustomerNumber
字段。 我们有数百名不同的人使用该系统(每个人都有自己的登录名和自己的 CustomerNumber
列表)。 单个用户最多可能拥有 100,000 个客户。 许多人的数量少于 100。
有些人只在客户编号字段中输入实际数字,而另一些人则混合使用不同的数字。 系统允许 20 个字符,可以是 AZ、0-9 或破折号,并将它们存储在 VARCHAR2(20) 中。 任何小写字母在存储之前都会变成大写字母。
现在,假设我们有一个简单的报告,其中列出了特定用户的所有客户,并按客户编号排序。 例如,
SELECT CustomerNumber,CustomerName
FROM Customer
WHERE User = ?
ORDER BY CustomerNumber;
这是一个幼稚的解决方案,因为只使用数字的人不希望看到简单的字母排序(其中“10”在“9”之前)。
我不想向用户询问有关其数据的任何不必要的问题。
我正在使用 Oracle,但我认为看到其他数据库的一些解决方案会很有趣。 请注明您的答案适用于哪个数据库。
您认为实现这一目标的最佳方法是什么?
Our application has a CustomerNumber
field. We have hundreds of different people using the system (each has their own login and their own list of CustomerNumber
s). An individual user might have at most 100,000 customers. Many have less than 100.
Some people only put actual numbers into their customer number fields, while others use a mixture of things. The system allows 20 characters which can be A-Z, 0-9 or a dash, and stores these in a VARCHAR2(20). Anything lowercase is made uppercase before being stored.
Now, let's say we have a simple report that lists all the customers for a particular user, sorted by Customer Number. e.g.
SELECT CustomerNumber,CustomerName
FROM Customer
WHERE User = ?
ORDER BY CustomerNumber;
This is a naive solution as the people that only ever use numbers do not want to see a plain alphabetic sort (where "10" comes before "9").
I do not wish to ask the user any unnecessary questions about their data.
I'm using Oracle, but I think it would be interesting to see some solutions for other databases. Please include which database your answer works on.
What do you think the best way to implement this is?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
也许您最好的选择是预先计算一个单独的列并将其用于订购并使用客户编号进行显示。 这可能涉及将任何内部整数用 0 填充到固定长度。
另一种可能性是对返回的结果进行后选择排序。
Jeff Atwood 整理了一篇博客,发布了一些内容人们计算人类友好的排序顺序。
Probably your best bet is to pre-calculate a separate column and use that for ordering and use the customer number for display. This would probably involve 0-padding any internal integers to a fixed length.
The other possibility is to do your sorting post-select on the returned results.
Jeff Atwood has put together a blog posting about how some people calculate human friendly sort orders.
在 Oracle 10g 中:
这将按数字的第一次出现进行排序,而不考虑其位置,即:
customer1
customer1
customer1
customer1
customer1
customer1
customer1 客户2 < 客户10
客户1omer? 客户1
cust8omer1 ? cust8omer2
,其中
?
表示顺序未定义。对于大多数情况来说这已经足够了。
要强制对情况
2
进行排序,您可以将REGEXP_INSTR(cust_name, '[0-9]', n)
添加到ORDER BY
列出n
次,强制在第n
(2nd
、3rd
等)组第一次出现时排序的数字。要对案例
3
强制排序,您可以将TO_NUMBER(REGEXP_SUBSTR(cust_name, '[0-9]+', n))
添加到ORDER BY
列出n
次,强制执行n
的顺序。 一组数字。实际上,我写的查询就足够了。
您可以在这些表达式上创建基于函数的索引,但您需要使用提示强制执行它,并且无论如何都会执行一次
SORT ORDER BY
,因为CBO< /code> 不信任基于函数的索引,不足以允许对其进行
ORDER BY
。In Oracle 10g:
This will sort by the first occurence of number, not regarding it's position, i. e.:
customer1 < customer2 < customer10
cust1omer ? customer1
cust8omer1 ? cust8omer2
, where a
?
means that the order is undefined.That suffices for most cases.
To force sort order on case
2
, you may add aREGEXP_INSTR(cust_name, '[0-9]', n)
toORDER BY
listn
times, forcing order on the first appearance ofn
-th (2nd
,3rd
etc.) group of digits.To force sort order on case
3
, you may add aTO_NUMBER(REGEXP_SUBSTR(cust_name, '[0-9]+', n))
toORDER BY
listn
times, forcing order ofn
-th. group of digits.In practice, the query I wrote is enough.
You may create a function based index on these expressions, but you'll need to force it with a hint, and a one-pass
SORT ORDER BY
will be performed anyway, as theCBO
doesn't trust function-base indexes enough to allow anORDER BY
on them.您可以有一个数字列 [CustomerNumberInt],仅当 CustomerNumber 为纯数字时才使用(否则为 NULL [1]),然后
[1] 取决于您的 SQL 版本如何处理 ORDER BY 中的 NULL,您可能希望将其默认为零(或无穷大!)
You could have a numeric column [CustomerNumberInt] that is only used when the CustomerNumber is purely numeric (NULL otherwise[1]), then
[1] depending on how your SQL version handles NULLs in ORDER BY you might want to default it to zero (or infinity!)
我有一个类似的可怕情况,并开发了一个适当的可怕函数来处理它(SQLServer)
在我的情况下,我有一个“单元”表(这是学生的工作跟踪系统,因此在这种情况下的单元代表一门课程他们正在做)。 单位有一个代码,大部分是纯数字的,但由于各种原因,它被做成了 varchar,并且他们决定在一些代码上添加最多 5 个字符的前缀。 所以他们期望 53,123,237,356 能够正常排序,但 T53, T123, T237, T356
UnitCode is a nvarchar(30)
这是函数的主体:
写完后我想朝自己的脸开枪,但它有效但似乎不起作用当服务器运行时杀死它。
I have a similar horrible situation and have developed a suitably horrible function to deal with it (SQLServer)
In my situation I have a table of "units" (this is a work-tracking system for students, so unit in this context represents a course they're doing). Units have a code, which for the most part is purely numeric, but for various reasons it was made a varchar and they decided to prefix some by up to 5 characters. So they expect 53,123,237,356 to sort normally, but also T53, T123, T237, T356
UnitCode is a nvarchar(30)
Here's the body of the function:
I wanted to shoot myself in the face after writing that, however it works and seems not to kill the server when it runs.
我在 SQL SERVER 中使用了它并且工作得很好:这里的解决方案是在数字值前面填充一个字符,以便所有的字符串长度都相同。
下面是使用该方法的示例:
100 应替换为该列的实际长度。
I used this in SQL SERVER and working great: Here the solution is to pad the numeric values with a character in front so that all are of the same string length.
Here is an example using that approach:
The 100 should be replaced with the actual length of that column.