web-dev-qa-db-fra.com

Tri numérique du champ varchar dans MySQL

J'ai un champ number de type varchar. Même s'il est de type varchar, il stocke des valeurs entières avec des zéros non significatifs. Un tri les ordonne lexicographiquement ("42" vient avant "9"). Comment puis-je commander par valeurs numériques ("9" à venir avant "42")?

Actuellement, j'utilise la requête:

SELECT * FROM table ORDER BY number ASC
37
wow

Il y a quelques façons de le faire:

  1. Stockez-les sous forme de valeurs numériques plutôt que de chaînes. Vous avez déjà tenu compte de cela, car vous souhaitez conserver des chaînes telles que 00100 avec les zéros à gauche.
  2. Ordonner par les chaînes exprimées sous forme numérique. Cela fonctionnera, mais sachez que cela nuit aux performances des bases de données de taille décente. Les fonctions par ligne ne s'adaptent pas vraiment bien.
  3. Ajoutez une troisième colonne qui est l'équivalent numérique de la chaîne et de l'index sur celle-ci. Utilisez ensuite un déclencheur d'insertion/mise à jour pour vous assurer qu'il est défini correctement chaque fois que la colonne de chaîne est modifiée.

Étant donné que la grande majorité des bases de données sont lues beaucoup plus souvent qu'écrites, cette troisième option amortit le coût du calcul (effectué lors de l'insertion/de la mise à jour) sur toutes les sélections. Vos sélections seront extrêmement rapides car ils utilisent la colonne numérique pour passer commande (et aucune fonction par ligne).

Vos insertions et mises à jour seront plus lentes mais c'est le prix que vous payez et, pour être honnête, cela vaut la peine d'être payé.

L'utilisation du déclencheur conserve les propriétés ACID de la table puisque les deux colonnes sont conservées à l'étape. Et c’est un idiome bien connu que vous pouvez généralement échanger de l’espace contre du temps dans la plupart des optimisations de performances.

Nous avons utilisé cette "astuce" dans de nombreuses situations, telles que le stockage de versions de noms de famille minuscules aux côtés des noms originaux (au lieu d'utiliser tolower), la longueur des chaînes d'identification permettant de trouver tous les utilisateurs avec des caractères à 7 len) et ainsi de suite.

N'oubliez pas qu'il est correct de revenir de la troisième forme normale de performance pour autant que vous en compreniez (et en atténuiez) les conséquences.

37
paxdiablo

Essaye ça

SELECT * FROM table_name ORDER BY CAST(field_name as SIGNED INTEGER) ASC
65
bobs

En fait, j'ai trouvé quelque chose d'intéressant:

SELECT * FROM mytable ORDER BY LPAD(lower(mycol), 10,0) DESC

Cela vous permet de commander le champ de la manière suivante:

1
2
3
10
A
A1
B2
10A
111
26
workdreamer
SELECT * FROM table ORDER BY number + 0
19
shantanuo

Trick je viens d'apprendre. Ajoutez '+0' à la clause d'ordre de champ varchar:

SELECT * FROM table ORDER BY number+0 ASC

Je vois maintenant cette réponse ci-dessus. Je me demande s'il s'agit d'une conversion du champ et d'un entier. Je n'ai pas comparé les performances. Travailler bien.

14
alexii

Pour un tableau avec des valeurs telles que Er353, ER 280, ER 30, ER36, le tri par défaut donnera ER280 ER30 ER353 ER36

select fieldname,substring(fieldname, 1, 2) as bcd, CONVERT(SUBSTRING(fieldname, 3, 9),UNSIGNED INTEGER) AS num from table_name order by bcd,num;

les résultats seront dans cet ordre ER30 ER36 ER280 ER353

5
ChAnDu353

vous pouvez obtenir une commande en fonction de vos besoins, ma requête SQL suivante

SELECT * FROM mytable ORDER BY ABS(mycol)
1

étant donné une colonne username contenant VARCHAR comme ceci:

username1
username10
username100

on pourrait faire:

SELECT username,
CONVERT(REPLACE(username, 'username', ''), UNSIGNED INTEGER) AS N
FROM users u
WHERE username LIKE 'username%'
ORDER BY N;

ce n'est pas bon marché, mais fait le travail.

1
minusf

SELECT * FROM table ORDER BY number ASC

Devrait afficher ce que vous voulez afficher .. vous semblez le trier par id ou number n'est pas défini comme integer pour le moment.

0
Or Weinberger