Est-il possible de classer les lignes de résultats par une colonne varchar
convertie en integer
dans Postgres 8.3?
C'est absolument possible.
ORDER BY varchar_column::int
Assurez-vous d'avoir des littéraux entiers valides dans votre colonne varchar
ou vous obtenez une exception. (Les espaces blancs de début et de fin sont corrects - ils seront automatiquement coupés.)
Si tel est le cas, alors pourquoi ne pas convertir la colonne en integer
pour commencer? Plus petit, plus rapide, plus propre, plus simple.
Pour supprimer les caractères non numériques avant la distribution et éviter ainsi les exceptions possibles:
ORDER BY NULLIF(regexp_replace(varchar_column, '\D', '', 'g'), '')::int
L'expression regexp_replace()
supprime efficacement tous les non-chiffres, donc seuls les chiffres restent ou une chaîne vide. (Voir ci-dessous.)
\D
Est un raccourci pour la classe de caractères [^[:digit:]]
, Ce qui signifie tous les non-chiffres ([^0-9]
).
Dans les anciennes versions de Postgres avec le paramètre obsolète standard_conforming_strings = off
, Vous devez utiliser la syntaxe de chaîne d'échappement Posix E'\\D'
Pour échapper à la barre oblique inverse \
. C'était par défaut dans Postgres 8.3, vous en aurez donc besoin pour votre version obsolète.
Le 4ème paramètre g
est pour "globalement!, demandant de remplacer tous les occurrences, pas seulement la première.
Vous mai souhaitez autoriser un tiret de tête (-
) Pour les nombres négatifs.
Si la chaîne n'a aucun chiffre, le résultat est une chaîne vide qui n'est pas valide pour un transtypage en integer
. Convertissez les chaînes vides en NULL
avec NULLIF
. (Vous pourriez plutôt envisager 0
.)
Le résultat est garanti valide. Cette procédure est pour un cast vers integer
comme demandé dans le corps de la question, pas pour numeric
comme le titre le mentionne.
Une façon est un index sur une expression . (Lien vers la version 8.3 du manuel.)
CREATE INDEX tbl_varchar_col2int_idx ON tbl
(cast(NULLIF(regexp_replace(varchar_column, E'\\D', '', 'g'), '') AS integer));
Utilisez ensuite la même expression dans la clause ORDER BY
:
ORDER BY
cast(NULLIF(regexp_replace(varchar_column, E'\\D', '', 'g'), '') AS integer)
Testez avec EXPLAIN ANALYZE
Si l'index fonctionnel est réellement utilisé.
De plus, si vous souhaitez commander par une colonne de texte qui a quelque chose de convertible à flotter, alors cela le fait:
select *
from your_table
order by cast(your_text_column as double precision) desc;