自然或人为排序顺序

Posted

技术标签:

【中文标题】自然或人为排序顺序【英文标题】:Natural or Human Sort order 【发布时间】:2017-09-12 16:00:24 【问题描述】:

我已经为此工作了几个月。我只是无法获得natural(真正的字母数字)结果。我很震惊,我无法得到它们,因为自 1992 年以来我一直能够在 RPG 中使用 EBCDIC

我正在寻找 SQL、VBS 或简单的 excel 或 access 中的任何解决方案。这是我的数据:

299-8, 
3410L-87, 
3410L-88, 
420-A20, 
420-A21, 
420A-40, 
4357-3, 
AN3H10A, 
K117GM-8, 
K129-1, 
K129-15, 
K271B-200L, 
K271B-38L, 
K271D-200EL, 
KD1051, 
KD1062, 
KD1092, 
KD1108, 
KD1108, 
M8000-3, 
MS24665-1, 
SK271B-200L, 
SAYA4008

我正在寻找的顺序是真正的字母数字顺序如下:

AN3H10A, 
KD1051, 
KD1062, 
KD1092, 
KD1108, 
KD1108, 
K117GM-8, 
K129-1, 
K129-15, 
MS24665-1,
M8000-3, 
SAYA4008, 
SK271B-200L

库存是 7800 条记录,所以我在处理能力方面也遇到了一些问题。

任何帮助将不胜感激。

杰夫

【问题讨论】:

数字后字母如何比其他方式更自然? 真正的字母数字在字母数字字符串的每一列中首先对字母进行加权。它来自 bin 卡,然后是平面文件。固定字段宽度会导致排序问题,因为它们不是按每个字符的位置排序的。 【参考方案1】:

在原生 Excel 中,您可以添加多个排序列以返回每个字符的 ASCII 码,但如果字符是数字,则在代码中添加一个大数字(例如 1000)。

然后对每个辅助列进行排序,包括表中的第一列,但不在排序中。

公式:

=IFERROR(CODE(MID($A1,COLUMNS($A:A),1))+AND(CODE(MID($A1,COLUMNS($A:A),1))>=48,CODE(MID($A1,COLUMNS($A:A),1))<=57)*1000,"")

排序对话框:

结果:

您可以使用 VBA 实现类似的算法,也可能使用 SQL。我不知道 VBS 或 Access。

【讨论】:

我喜欢这种方法的结果。我只是缺少一些关于如何创建 ASCII 排序的基础知识。有没有机会一步一步来创造你的结果? @Jeff 你不明白什么?你是如何尝试实现这一点的?你有没有在任何地方输入公式?结果如何? 我在B1中实现了公式。我了解您的思考过程是如何将每个字符列成一个 ASCii 顺序(我认为)。 @Jeff 只需选择 B1 并填写。然后选择 B1:Bn 并向右填写。然后查看屏幕截图以对每一列进行排序。 B1:Bn!!!我知道更深层次的东西,但从来没有想过横向。效果很好,但是在对每一列进行排序之后,列 a 仍然乱序。我不确定你是如何重新排序的。【参考方案2】:

您可以尝试使用格式按顺序左填充字符串

select column
from my_table 
order by  Format(column, "0000000000")

【讨论】:

【参考方案3】:

添加排序列:

, iif (left(fieldname, 1) between '0' and '9', 1, 0) sortField
etc
order by sortField, FieldName

【讨论】:

【参考方案4】:

假设您在“A”列中有数据。如果你把这个公式放在“B”列=IFERROR(IF(LEFT(A1,1)+1&gt;0,"ZZZZZZZ "&amp;A1,A1),A1),它会自动在所有数值前面加上Z,这样当你对A-Z进行排序时,它们自然会出现在所有字母值之后。稍后您可以找到并替换那个有趣的 ZZZZZZ 字符串...

【讨论】:

【参考方案5】:

有很多方法,但在这种情况下,构建两列分隔分隔符 (-) 的工作量可能最少。

然后您“填充”结果(空格或 0)右对齐,然后对两列进行排序。

所以在查询构建器中我们有这个:

SELECT Field1, 
Format(
Mid(field1,1,IIf(InStr(field1,"-")=0,50,InStr(field1,"-")-1)),
">@@@@@@@@@@") AS Expr1,
Format(
Mid(field1,IIf(InStr(field1,"-")=0,99,InStr(field1,"-")+1)),
">@@@@@@@@@@") AS Expr2
FROM Data

当我们运行上面的原始查询时,我们会得到:

所以现在在查询生成器中,只需对第一个派生列进行排序,然后对第二个派生列进行排序。

例如:

运行查询,我们得到这个结果:

编辑:

看着你想要的结果,看起来上面的排序是错误的。我们必须正确并用 0 填充。

所以这第二次尝试:

SELECT Field1, 
Left(Mid(field1,1,IIf(InStr(field1,"-")=0,30,InStr(field1,"-")-1)) 
& String(30,"0"),30) AS Expr1, 
Left(Mid(field1,IIf(InStr(field1,"-")=0,99,InStr(field1,"-")+1)) 
& String(30,"0"),30) AS Expr2
FROM Data

结果是这样的:

鉴于您的表很小,那么上面的查询应该会执行得很好。

【讨论】:

以上是关于自然或人为排序顺序的主要内容,如果未能解决你的问题,请参考以下文章

多维数组的排序顺序跨浏览器兼容并具有“自然情况”

Bash 排序类似于 Windows 的“自然排序顺序”

按自然顺序对字典键进行排序[重复]

TreeSet对非自然顺序元素的排序

Java自然排序键的Multimap,但是按照添加元素的顺序排序的集合

对字符串中字符进行自然顺序排序(基本类型排序)-冒泡算法实现