跟进Sivaram Chintalapudi提出的这个问题,我感兴趣的是在 PostgreSQL 中对包含多位数字和单词/字母混合的字符串进行自然或“人性化”排序是否可行。没有固定的字符串中的单词和数字的模式,并且字符串中可能有多个多位数字。
我经常看到这样做的唯一地方是在 Mac OS 的 Finder 中,它自然地对包含混合数字和单词的文件名进行排序,将“20”放在“3”之后,而不是之前。
所需的整理顺序将由一种算法产生,该算法将每个字符串在字母数字边界处分成块,然后对每个部分进行排序,将具有正常整理的字母块和数字块视为整数以进行整理。所以:
'AAA2fred'
将成为('AAA',2,'fred')
并将'AAA10bob'
成为('AAA',10,'bob')
。然后可以根据需要对这些进行排序:
regress=# WITH dat AS ( VALUES ('AAA',2,'fred'), ('AAA',10,'bob') )
regress-# SELECT dat FROM dat ORDER BY dat;
dat
--------------
(AAA,2,fred)
(AAA,10,bob)
(2 rows)
与通常的字符串排序规则相比:
regress=# WITH dat AS ( VALUES ('AAA2fred'), ('AAA10bob') )
regress-# SELECT dat FROM dat ORDER BY dat;
dat
------------
(AAA10bob)
(AAA2fred)
(2 rows)
然而,记录比较方法并没有推广,因为 Pg 不会比较 ROW(..) 构造或不等数量条目的记录。
鉴于此 SQLFiddle中的示例数据,默认的 en_AU.UTF-8 排序规则会产生排序:
1A, 10A, 2A, AAA10B, AAA11B, AAA1BB, AAA20B, AAA21B, X10C10, X10C2, X1C1, X1C10, X1C3, X1C30, X1C4, X2C1
但我想要:
1A, 2A, 10A, AAA1BB, AAA10B, AAA11B, AAA20B, AAA21B, X1C1, X1C3, X1C4, X1C10, X1C30, X2C1, X10C10, X10C2
我目前正在使用 PostgreSQL 9.1,但只有 9.2 的建议就可以了。我对如何实现有效的字符串拆分方法以及如何在所描述的交替字符串-然后-数字排序规则中比较生成的拆分数据感兴趣。或者,当然,在不需要拆分字符串的完全不同和更好的方法上。
PostgreSQL 似乎不支持比较器函数,否则这可以通过递归比较器和类似函数的东西相当容易地ORDER USING comparator_fn
完成comparator(text,text)
。唉,这种语法是虚构的。
更新: 关于该主题的博客文章。