Basandosi sui dati del test, ma funziona con dati arbitrari. Funziona con qualsiasi numero di elementi nella stringa.
Registra un tipo composto composto da un text
e un integer
valore una volta per database. Lo chiamo ai
:
CREATE TYPE ai AS (a text, i int);
Il trucco è formare un array di ai
da ogni valore nella colonna.
regexp_matches()
con lo schema (\D*)(\d*)
e il g
l'opzione restituisce una riga per ogni combinazione di lettere e numeri. Più una riga penzolante irrilevante con due stringhe vuote '{"",""}'
Filtrarlo o sopprimerlo aggiungerebbe solo dei costi. Aggregalo in un array, dopo aver sostituito le stringhe vuote (''
) con 0
nel integer
componente (come ''
non può essere trasmesso a integer
).
NULL
i valori ordinano per primi - o devi metterli in un caso speciale - o usa l'intero shebang in un STRICT
funzione come propone @Craig.
Postgres 9.4 o successivo
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<>gioca qui
Postgres 9.1 (risposta originale)
Testato con PostgreSQL 9.1.5, dove regexp_replace()
aveva un comportamento leggermente diverso.
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
Aggiungi regexp_replace (left(data, 1), '[1-9]', '0')
come primo ORDER BY
elemento per occuparsi delle cifre iniziali e delle stringhe vuote.
Se caratteri speciali come {}()"',
può verificarsi, dovresti evitarli di conseguenza.
Suggerimento di @Craig per utilizzare una ROW
l'espressione si occupa di questo.
BTW, questo non verrà eseguito in sqlfiddle, ma lo fa nel mio cluster db. JDBC non è all'altezza. sqlfiddle si lamenta:
Il metodo org.postgresql.jdbc3.Jdbc3Array.getArrayImpl(long,int,Map) non è ancora implementato.
Da allora è stato risolto:http://sqlfiddle.com/#!17/fad6e/1