Bygger på dina testdata, men det här fungerar med godtyckliga data. Detta fungerar med valfritt antal element i strängen.
Registrera en sammansatt typ som består av en text och ett integer värde en gång per databas. Jag kallar det ai :
CREATE TYPE ai AS (a text, i int);
Tricket är att bilda en array av ai från varje värde i kolumnen.
regexp_matches() med mönstret (\D*)(\d*) och g alternativet returnerar en rad för varje kombination av bokstäver och siffror. Plus en irrelevant dinglande rad med två tomma strängar '{"",""}' Att filtrera eller undertrycka det skulle bara öka kostnaden. Aggregera detta till en array efter att ha ersatt tomma strängar ('' ) med 0 i integer komponent (som '' kan inte casta till integer ).
NULL värden sorteras först - eller så måste du använda specialfall för dem - eller använd hela shebang i en STRICT fungerar som @Craig föreslår.
Postgres 9.4 eller senare
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<>spela här
Postgres 9.1 (ursprungligt svar)
Testad med PostgreSQL 9.1.5, där regexp_replace() hade ett lite annorlunda beteende.
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
Lägg till regexp_replace (left(data, 1), '[1-9]', '0') som första ORDER BY objekt för att ta hand om inledande siffror och tomma strängar.
Om specialtecken som {}()"', kan inträffa, måste du undkomma dem i enlighet med detta.
@Craigs förslag att använda en ROW expression tar hand om det.
BTW, detta kommer inte att köras i sqlfiddle, men det gör det i mitt db-kluster. JDBC klarar inte av det. sqlfiddle klagar:
Metoden org.postgresql.jdbc3.Jdbc3Array.getArrayImpl(long,int,Map) är ännu inte implementerad.
Detta har sedan åtgärdats:https://sqlfiddle.com/#!17/fad6e/1