Voortbouwend op uw testgegevens, maar dit werkt met willekeurige gegevens. Dit werkt met een willekeurig aantal elementen in de string.
Registreer een samengesteld type bestaande uit één text
en één integer
waarde eenmaal per database. Ik noem het ai
:
CREATE TYPE ai AS (a text, i int);
De truc is om een array te vormen van ai
van elke waarde in de kolom.
regexp_matches()
met het patroon (\D*)(\d*)
en de g
optie retourneert één rij voor elke combinatie van letters en cijfers. Plus een irrelevante bungelende rij met twee lege strings '{"",""}'
Het filteren of onderdrukken zou alleen maar meer kosten opleveren. Voeg dit samen tot een array, na het vervangen van lege strings (''
) met 0
in het integer
component (als ''
kan niet worden gecast naar integer
).
NULL
waarden sorteer eerst - of je moet ze speciaal maken - of gebruik de hele shebang in een STRICT
functioneren zoals @Craig voorstelt.
Postgres 9.4 of hoger
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<>viool hier
Postgres 9.1 (oorspronkelijk antwoord)
Getest met PostgreSQL 9.1.5, waarbij regexp_replace()
had een iets ander gedrag.
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
Voeg regexp_replace (left(data, 1), '[1-9]', '0')
toe als eerste ORDER BY
item om voorloopcijfers en lege tekenreeksen op te lossen.
Als speciale tekens zoals {}()"',
kunnen voorkomen, moet u dienovereenkomstig ontsnappen.
Suggestie van @Craig om een ROW
te gebruiken expressie zorgt daarvoor.
BTW, dit wordt niet uitgevoerd in sqlfiddle, maar wel in mijn db-cluster. JDBC kan het niet aan. sqlfiddle klaagt:
Methode org.postgresql.jdbc3.Jdbc3Array.getArrayImpl(long,int,Map) is nog niet geïmplementeerd.
Dit is sindsdien opgelost:http://sqlfiddle.com/#!17/fad6e/1