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.