PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Ordem varchar string como numérica


É absolutamente possível.
ORDER BY varchar_column::int

Certifique-se de ter literais inteiros válidos em seu varchar coluna para cada entrada ou você obtém uma exceção invalid input syntax for integer: ... . (O espaço em branco à esquerda e à direita está ok - ele será cortado automaticamente.)

Se for esse o caso, por que não converter a coluna para integer começar com? Menor, mais rápido, mais limpo, mais simples.

Como evitar exceções?


Para remover caracteres que não sejam dígitos antes da conversão e, assim, evitar possíveis exceções:
ORDER BY NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '')::int

  • O regexp_replace() expression remove efetivamente todos os não dígitos, portanto, apenas os dígitos permanecem ou uma string vazia. (Ver abaixo.)

  • \D é um atalho para a classe de caracteres [^[:digit:]] , ou seja, todos os não dígitos ([^0-9] ).
    Nas versões antigas do Postgres com a configuração desatualizada standard_conforming_strings = off , você deve usar a sintaxe de string de escape Posix E'\\D' para escapar da barra invertida \ . Isso era padrão no Postgres 8.3, então você precisará disso para sua versão desatualizada.

  • O quarto parâmetro g é para "globalmente" , instruindo a substituir todos ocorrências, não apenas as primeiras.

  • Você pode deseja permitir um traço inicial (- ) para números negativos.

  • Se a string não tiver dígitos, o resultado será uma string vazia que não é válida para uma conversão para integer . Converter strings vazias para NULL com NULLIF . (Você pode considerar 0 em vez de.)

O resultado é garantido para ser válido. Este procedimento é para uma conversão para integer conforme solicitado no corpo da pergunta, não para numeric como o título menciona.

Como fazer isso rápido?


Uma maneira é um índice em uma expressão.
CREATE INDEX tbl_varchar_col2int_idx ON tbl
(cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer));

Em seguida, use a mesma expressão no ORDER BY cláusula:
ORDER BY
cast(NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '') AS integer)

Teste com EXPLAIN ANALYZE se o índice funcional realmente é usado.