Humanizowane lub naturalne sortowanie liczb mieszanych ciągów słów i liczb

Kontynuacjato pytanie przezSivaram Chintalapudi, Interesuje mnie, czy jest to praktyczne w PostgreSQLnaturalne - lub „humanizowane” - sortowanie „łańcuchów zawierających mieszankę wielocyfrowych liczb i słów / liter. W ciągach nie ma ustalonego wzorca słów i liczb, aw ciągu może występować więcej niż jedna wielocyfrowa liczba.

Jedyne miejsce, które widziałem to rutynowo, znajduje się w Finderze Mac OS, który sortuje nazwy plików zawierające naturalnie mieszane liczby i słowa, umieszczając „20” po „3”, a nie przed nim.

Żądany porządek sortowania byłby generowany przez algorytm, który dzieli każdy ciąg na bloki na granicy liczby literowej, a następnie porządkuje każdą część, traktując bloki literowe z normalnym sortowaniem i bloki liczbowe jako liczby całkowite do celów sortowania. Więc:

'AAA2fred' stanie się('AAA',2,'fred') i'AAA10bob' stanie się('AAA',10,'bob'). Można je następnie sortować według potrzeb:

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)

w porównaniu ze zwykłym porządkowaniem sortowania ciągów:

regress=# WITH dat AS ( VALUES ('AAA2fred'), ('AAA10bob') )
regress-# SELECT dat FROM dat ORDER BY dat;
    dat     
------------
 (AAA10bob)
 (AAA2fred)
(2 rows)

Jednak metoda porównywania rekordów nie uogólnia, ponieważ Pg nie porównuje konstrukcji ROW (..) lub zapisów nierównej liczby wpisów.

Biorąc pod uwagę przykładowe danew tym SQLFiddle domyślne sortowanie en_AU.UTF-8 tworzy kolejność:

1A, 10A, 2A, AAA10B, AAA11B, AAA1BB, AAA20B, AAA21B, X10C10, X10C2, X1C1, X1C10, X1C3, X1C30, X1C4, X2C1

ale ja chcę:

1A, 2A, 10A, AAA1BB, AAA10B, AAA11B, AAA20B, AAA21B, X1C1, X1C3, X1C4, X1C10, X1C30, X2C1, X10C10, X10C2

W tej chwili pracuję z PostgreSQL 9.1, ale sugestie tylko w wersji 9.2 byłyby w porządku. Interesuje mnie rada, jak uzyskać skuteczną metodę dzielenia łańcuchów i jak następnie porównać uzyskane dane podzielone w opisanym naprzemiennym sortowaniu łańcuchów i liczb. Lub, oczywiście, na zupełnie innych i lepszych podejściach, które nie wymagają dzielenia łańcuchów.

PostgreSQL nie wydaje się obsługiwać funkcji komparatora, w przeciwnym razie można to zrobić dość łatwo za pomocą komparatora rekurencyjnego i czegoś podobnegoORDER USING comparator_fn i acomparator(text,text) funkcjonować. Niestety, ta składnia jest wyimaginowana.

Aktualizacja: Post na blogu na ten temat.

questionAnswers(6)

yourAnswerToTheQuestion