È assolutamente possibile.
ORDER BY varchar_column::int
Assicurati di avere valori interi validi nel tuo varchar
colonna per ogni voce o ottieni un'eccezione invalid input syntax for integer: ...
. (Lo spazio bianco iniziale e finale va bene:verrà tagliato automaticamente.)
Se è così, però, perché non convertire la colonna in integer
iniziare con? Più piccolo, più veloce, più pulito, più semplice.
Come evitare le eccezioni?
Per rimuovere i caratteri non numerici prima del cast e quindi evitare possibili eccezioni:
ORDER BY NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '')::int
-
Il
regexp_replace()
l'espressione rimuove efficacemente tutte le non cifre, quindi rimangono solo le cifre o una stringa vuota. (Vedi sotto.) -
\D
è un'abbreviazione per la classe di caratteri[^[:digit:]]
, ovvero tutte le non cifre ([^0-9]
).
Nelle vecchie versioni di Postgres con l'impostazione obsoletastandard_conforming_strings = off
, devi usare la sintassi della stringa di escape PosixE'\\D'
per evitare la barra rovesciata\
. Questo era l'impostazione predefinita in Postgres 8.3, quindi ti servirà per la tua versione obsoleta. -
Il 4° parametro
g
sta per "globalmente" , indicando di sostituire tutti occorrenze, non solo la prima. -
puoi vuoi consentire un trattino iniziale (
-
) per i numeri negativi. -
Se la stringa non ha alcuna cifra, il risultato è una stringa vuota che non è valida per un cast a
integer
. Converti stringhe vuote inNULL
conNULLIF
. (Potresti considerare0
invece.)
Il risultato è garantito per essere valido. Questa procedura è per un cast a integer
come richiesto nel corpo della domanda, non per numeric
come dice il titolo.
Come renderlo veloce?
Un modo è un indice su un'espressione.
CREATE INDEX tbl_varchar_col2int_idx ON tbl
(cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer));
Quindi usa la stessa espressione in ORDER BY
clausola:
ORDER BY
cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer)
Prova con EXPLAIN ANALYZE
se l'indice funzionale viene effettivamente utilizzato.