Bygger på dine testdata, men dette fungerer med vilkårlige data. Dette fungerer med et vilkårligt antal elementer i strengen.
Registrer en sammensat type, der består af én text
og et integer
værdi én gang pr. database. Jeg kalder det ai
:
CREATE TYPE ai AS (a text, i int);
Tricket er at danne et array af ai
fra hver værdi i kolonnen.
regexp_matches()
med mønsteret (\D*)(\d*)
og g
option returnerer én række for hver kombination af bogstaver og tal. Plus en irrelevant dinglende række med to tomme strenge '{"",""}'
Filtrering eller undertrykkelse af det ville blot øge omkostningerne. Aggreger dette i en matrix efter at have erstattet tomme strenge (''
) med 0
i integer
komponent (som ''
kan ikke castes til integer
).
NULL
værdier sorteres først - eller du er nødt til at bruge dem i særlige tilfælde - eller brug hele shebang i en STRICT
funktion som @Craig foreslår.
Postgres 9.4 eller nyere
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<>spil her
Postgres 9.1 (oprindeligt svar)
Testet med PostgreSQL 9.1.5, hvor regexp_replace()
havde en lidt anderledes adfærd.
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
Tilføj regexp_replace (left(data, 1), '[1-9]', '0')
som første ORDER BY
element for at tage sig af førende cifre og tomme strenge.
Hvis specialtegn som {}()"',
kan forekomme, bliver du nødt til at undslippe dem i overensstemmelse hermed.
@Craigs forslag om at bruge en ROW
expression tager sig af det.
BTW, dette vil ikke køre i sqlfiddle, men det gør det i min db-klynge. JDBC er ikke op til det. sqlfiddle klager:
Metoden org.postgresql.jdbc3.Jdbc3Array.getArrayImpl(long,int,Map) er endnu ikke implementeret.
Dette er siden blevet rettet:http://sqlfiddle.com/#!17/fad6e/1