Чтобы не заниматься программированием в PostgreSQL, в котором натуральной сортировки для такого случая я не нашёл, решением может быть хранить ваши строки не
as is, а отдельно буквы и массив цифр, т.е. вместо одного поля
VARCHAR
для всей строки использовать 2 поля: строка
VARCHAR
для букв и массив чисел
INTEGER[]
:
CREATE TABLE test (
"letters" VARCHAR(20),
"digits" INTEGER[]
);
INSERT INTO test
("letters", "digits")
VALUES
('ЧС', '{1, 1}'),
('ЧС', '{1, 2}'),
('ЧС', '{1, 3, 1}'),
('ЧС', '{1, 10}'),
('ЧС', '{1, 11, 1}'),
('П', '{1, 1}'),
('П', '{1, 2}'),
('П', '{2, 10}');
SQL тогда получается банальным - сортировка просто по этим двум полям, а собрать нужную строку можно прямо в запросе:
SELECT letters || '.' || array_to_string(digits, '.') from test order by letters, digits;
Поиграться:
https://www.db-fiddle.com/f/kGBapu86EXBuMZ6Bh6mGfe/1