Въз основа на вашите тестови данни, но това работи с произволни данни. Това работи с произволен брой елементи в низа.
Регистрирайте съставен тип, съставен от един text и едно integer стойност веднъж на база данни. Наричам го ai :
CREATE TYPE ai AS (a text, i int);
Номерът е да се формира масив от ai от всяка стойност в колоната.
regexp_matches() с шаблона (\D*)(\d*) и g опцията връща един ред за всяка комбинация от букви и цифри. Плюс един неуместен висящ ред с два празни низа '{"",""}' Филтрирането или потискането му само би увеличило разходите. Обединете това в масив, след като замените празните низове ('' ) с 0 в integer компонент (като '' не може да бъде прехвърлен към integer ).
NULL стойностите първо сортирайте - или трябва да ги поставите в специален случай - или използвайте целия шебан в STRICT функция, както предлага @Craig.
Postgres 9.4 или по-нова версия
SELECT data
FROM alnum
ORDER BY ARRAY(SELECT ROW(x[1], CASE x[2] WHEN '' THEN '0' ELSE x[2] END)::ai
FROM regexp_matches(data, '(\D*)(\d*)', 'g') x)
, data;
db<>цигулка тук
Postgres 9.1 (оригинален отговор)
Тествано с PostgreSQL 9.1.5, където regexp_replace() имаше малко по-различно поведение.
SELECT data
FROM (
SELECT ctid, data, regexp_matches(data, '(\D*)(\d*)', 'g') AS x
FROM alnum
) x
GROUP BY ctid, data -- ctid as stand-in for a missing pk
ORDER BY regexp_replace (left(data, 1), '[0-9]', '0')
, array_agg(ROW(x[1], CASE x[2] WHEN '' THEN '0' ELSE x[2] END)::ai)
, data -- for special case of trailing 0
Добавете regexp_replace (left(data, 1), '[1-9]', '0') като първи ORDER BY елемент, който се грижи за водещите цифри и празните низове.
Ако специални знаци като {}()"', може да възникне, ще трябва да ги избягате съответно.
Предложение на @Craig за използване на ROW Expression се грижи за това.
BTW, това няма да се изпълни в sqlfiddle, но се изпълнява в моя db клъстер. JDBC не е до това. sqlfiddle се оплаква:
Методът org.postgresql.jdbc3.Jdbc3Array.getArrayImpl(long,int,Map) все още не е внедрен.
Оттогава това беше коригирано:https://sqlfiddle.com/#!17/fad6e/1