sql >> Base de Datos >  >> RDS >> PostgreSQL

Ordenar cadena varchar como numérica

Es absolutamente posible.

ORDER BY varchar_column::int

Asegúrese de tener literales enteros válidos en su varchar columna para cada entrada o obtiene una excepción invalid input syntax for integer: ... . (Los espacios en blanco iniciales y finales están bien; se recortarán automáticamente).

Sin embargo, si ese es el caso, ¿por qué no convertir la columna a integer? ¿para empezar? Más pequeño, más rápido, más limpio, más simple.

¿Cómo evitar las excepciones?

Para eliminar caracteres que no sean dígitos antes de la conversión y así evitar posibles excepciones:

ORDER BY NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '')::int
  • El regexp_replace() expresión elimina efectivamente todos los que no son dígitos, por lo que solo quedan dígitos o una cadena vacía. (Ver más abajo).

  • \D es la abreviatura de la clase de carácter [^[:digit:]] , es decir, todos los que no sean dígitos ([^0-9] ).
    En versiones antiguas de Postgres con la configuración obsoleta standard_conforming_strings = off , debe usar la sintaxis de cadena de escape de Posix E'\\D' para escapar de la barra invertida \ . Esto era predeterminado en Postgres 8.3, por lo que lo necesitará para su versión obsoleta.

  • El cuarto parámetro g es para "globalmente" , indicando que se reemplacen todos ocurrencias, no solo las primeras.

  • Usted puede desea permitir un guión inicial (- ) para números negativos.

  • Si la cadena no tiene ningún dígito, el resultado es una cadena vacía que no es válida para una conversión a integer . Convierte cadenas vacías a NULL con NULLIF . (Puede considerar 0 en su lugar.)

Se garantiza que el resultado es válido. Este procedimiento es para una conversión a integer como se solicita en el cuerpo de la pregunta, no para numeric como lo menciona el título.

¿Cómo hacerlo rápido?

Una forma es un índice en una expresión.

CREATE INDEX tbl_varchar_col2int_idx ON tbl
(cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer));

Luego usa la misma expresión en el ORDER BY cláusula:

ORDER BY
cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer)

Prueba con EXPLAIN ANALYZE si el índice funcional realmente se usa.