web-dev-qa-db-fra.com

Ordre de la chaîne varchar sous forme numérique

Est-il possible de classer les lignes de résultats par une colonne varchar convertie en integer dans Postgres 8.3?

40
Jauzsika

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.

Comment éviter les exceptions?

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.


Comment faire vite?

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é.

97
Erwin Brandstetter

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;
4
Eric Leschinski