Ordenação humanizada ou natural de números de cordas mistas de palavras e números
Seguindo em frenteessa questão porSivaram Chintalapudi, Estou interessado em saber se é prático no PostgreSQL fazernatural - ou "humanizado" - classificação "de strings que contêm uma mistura de números de vários dígitos e palavras / letras. Não há um padrão fixo de palavras e números nas strings e pode haver mais de um número de vários dígitos em uma string.
O único lugar que eu vi isso feito rotineiramente é no Finder do Mac OS, que classifica nomes de arquivos contendo números mistos e palavras naturalmente, colocando "20" depois de "3", não antes dele.
A ordem de intercalação desejada seria produzida por um algoritmo que dividiria cada cadeia em blocos nos limites de números de letras, depois ordenaria cada parte, tratando blocos de letras com intercalação normal e blocos de números como inteiros para propósitos de intercalação. Assim:
'AAA2fred'
se tornaria('AAA',2,'fred')
e'AAA10bob'
se tornaria('AAA',10,'bob')
. Estes podem então ser classificados como desejado:
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)
em comparação com a ordem usual de intercalação de cadeias:
regress=# WITH dat AS ( VALUES ('AAA2fred'), ('AAA10bob') )
regress-# SELECT dat FROM dat ORDER BY dat;
dat
------------
(AAA10bob)
(AAA2fred)
(2 rows)
No entanto, a abordagem de comparação de registros não é generalizada porque a Pg não compara construções ROW (..) ou registros de números desiguais de entradas.
Dado os dados da amostraneste SQLFiddle o agrupamento padrão en_AU.UTF-8 produz a ordenação:
1A, 10A, 2A, AAA10B, AAA11B, AAA1BB, AAA20B, AAA21B, X10C10, X10C2, X1C1, X1C10, X1C3, X1C30, X1C4, X2C1
mas eu quero:
1A, 2A, 10A, AAA1BB, AAA10B, AAA11B, AAA20B, AAA21B, X1C1, X1C3, X1C4, X1C10, X1C30, X2C1, X10C10, X10C2
Eu estou trabalhando com o PostgreSQL 9.1 no momento, mas as sugestões somente 9.2 seriam boas. Estou interessado em obter conselhos sobre como obter um método eficiente de divisão de cadeias e como comparar os dados divididos resultantes no agrupamento alternativo string-then-number descrito. Ou, claro, em abordagens completamente diferentes e melhores que não exigem divisão de strings.
O PostgreSQL não parece suportar funções de comparação, caso contrário isso pode ser feito facilmente com um comparador recursivo e algo comoORDER USING comparator_fn
e umcomparator(text,text)
função. Infelizmente, essa sintaxe é imaginária.
Atualizar: Postagem no blog sobre o tema.