Convertir du texte en nombre dans une requête MySQL

138

Est-il possible de convertir du texte en nombre dans une requête MySQL? J'ai une colonne avec un identifiant qui se compose d'un nom et d'un nombre au format "nom-numéro". La colonne est de type VARCHAR. Je veux trier les lignes en fonction du nombre (lignes avec le même nom) mais la colonne est triée selon l'ordre des caractères, c'est-à-dire

name-1
name-11
name-12
name-2

Si je coupe le nombre, puis-je convertir le nombre «varchar» en nombre «réel» et l'utiliser pour trier les lignes? Je voudrais obtenir l'ordre suivant.

name-1
name-2
name-11
name-12

Je ne peux pas représenter le nombre dans une colonne distincte.

édité 2011-05-11 9:32

J'ai trouvé la solution suivante ... ORDER BY column * 1. Si le nom ne contient aucun nombre, est-il possible d'utiliser cette solution?

czuk
la source
1
nom est exactement le nom ou peut-il être n'importe quel caractère? Je veux dire: est-ce une chaîne de quatre caractères de long ou est-ce un vrai nom?
Marco
namepeut être n'importe quelle séquence de lettres.
czuk
1
duplication possible du tri naturel mysql
Shakti Singh

Réponses:

256

Cela devrait fonctionner:

SELECT field,CONVERT(SUBSTRING_INDEX(field,'-',-1),UNSIGNED INTEGER) AS num
FROM table
ORDER BY num;
Marco
la source
1
pouvez-vous ajouter une explication et un lien vers la documentation?
Angelo Fuchs
Ma chaîne est comme "nom-abc12". En ajoutant votre code, cela ne fonctionne que si les premiers caractères après "-" ne commencent pas par une lettre. @Marco Pouvez-vous me dire un moyen d'ignorer les lettres sans condition où?
Eduardo
1
@Eduardo ma requête est censée obtenir la chaîne après le "-" et la convertir en un nombre (ce DOIT être un nombre). Dans votre cas, je continuerais probablement à utiliser une expression régulière ...
Marco
L'expression régulière @Marco l'a fait, merci pour le conseil.
Eduardo
32

Vous pouvez utiliser SUBSTRINGet CONVERT:

SELECT stuff
FROM table
WHERE conditions
ORDER BY CONVERT(SUBSTRING(name_column, 6), SIGNED INTEGER);

name_columnest la colonne avec les valeurs "nom-". Le SUBSTRINGsupprime tout ce qui se trouve avant le sixième caractère (c'est-à-dire le préfixe "nom-"), puis CONVERTconvertit la gauche en un entier réel.

MISE À JOUR : Compte tenu de l'évolution des circonstances dans les commentaires (c'est-à-dire que le préfixe peut être n'importe quoi), vous devrez ajouter un LOCATEdans le mix:

ORDER BY CONVERT(SUBSTRING(name_column, LOCATE('-', name_column) + 1), SIGNED INTEGER);

Cela suppose bien sûr que le préfixe non numérique ne contient aucun trait d'union, mais le commentaire pertinent dit que:

name peut être n'importe quelle séquence de lettres

donc cela devrait être une hypothèse sûre.

mu est trop court
la source
En réponse à mon commentaire, il nous a dit que le nom pouvait être n'importe quelle séquence de caractères, donc je ne suis pas sûr que vous puissiez l'utiliser SUBSTRING(name_column, 6). Je sais, vous l'avez posté quand il ne nous l'a pas dit ...
Marco
@Marco: Merci pour la mise en garde, j'ai ajouté une mise à jour qui devrait prendre en charge les nouvelles informations sur les préfixes. Mais oui, votre SUBSTRING_INDEX est plus agréable.
mu est trop court
23

Utilisez simplement CAST,

CAST(column_name AS UNSIGNED)

Le type du résultat de conversion peut être l'une des valeurs suivantes:

BINARY[(N)]
CHAR[(N)]
DATE
DATETIME
DECIMAL[(M[,D])]
SIGNED [INTEGER]
TIME
UNSIGNED [INTEGER]
Sibin John Mattappallil
la source
14

Vous pouvez utiliser CAST () pour convertir une chaîne en un entier. par exempleSELECT CAST('123' AS INTEGER);

Verdesmarald
la source
15
Cette version est-elle spécifique? J'ai besoin de l'utiliser SELECT CAST('123' AS SIGNED INTEGER);ou SELECT CAST('123' AS UNSIGNED INTEGER);de le faire fonctionner.
Hobo
10
SELECT *, CAST(SUBSTRING_INDEX(field, '-', -1) AS UNSIGNED) as num FROM tableName ORDER BY num;
Gaurav
la source
1
Êtes-vous sûr que ORDER BY utilise num comme nombre sans utiliser CONVERT? Je ne suis pas sûr, mais ça peut l'être .. Je me demande juste :)
Marco
4

une manière simple SELECT '123' + 0

VRK RAO
la source
Bien que ce code puisse aider à résoudre le problème, fournir un contexte supplémentaire concernant la raison et / ou la manière dont il répond à la question améliorerait considérablement sa valeur à long terme. Veuillez modifier votre réponse pour ajouter des explications.
Toby Speight le
Cela n'a pas répondu à la question mais c'était la réponse que je cherchais.
Sagar Shah
votre solution est la plus élégante et la plus pratique - malheureusement vous ne l'avez pas fournie dans le contexte de la question avec une expression spécifique pour l'exemple donné - veuillez la modifier pour qu'elle soit spécifique.
chukko
2

si votre clé primaire est une chaîne dans un format comme

ABC / EFG / EE / 13/123 (numéro de séquence),
ce type de chaîne peut être facilement utilisé pour le tri avec le délimiteur ("/")

nous pouvons utiliser la requête suivante pour commander une table avec ce type de clé

SELECT * FROM `TABLE_NAME` ORDER BY 
CONVERT(REVERSE(SUBSTRING(REVERSE(`key_column_name`), 1, LOCATE('/', REVERSE(`key_column_name`)) - 1)) , UNSIGNED INTEGER) DESC
Harsha
la source
0
cast(REGEXP_REPLACE(NameNumber, '[^0-9]', '') as UNSIGNED)
Jayram Kumar
la source
-5

Une façon générique de faire:

SELECT * FROM your_table ORDER BY LENTH(your_column) ASC, your_column ASC
Azzu
la source