Convierta texto en número en la consulta MySQL

138

¿Es posible convertir texto en número dentro de la consulta MySQL? Tengo una columna con un identificador que consta de un nombre y un número en el formato de "nombre-número". La columna tiene el tipo VARCHAR. Quiero ordenar las filas según el número (filas con el mismo nombre) pero la columna se ordena según el orden de los caracteres, es decir

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

Si corto el número, ¿puedo convertir el número 'varchar' en el número 'real' y usarlo para ordenar las filas? Me gustaría obtener el siguiente orden.

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

No puedo representar el número como una columna separada.

editado 2011-05-11 9:32

He encontrado la siguiente solución ... ORDER BY column * 1. Si el nombre no contiene ningún número, ¿es seguro usar esa solución?

czuk
fuente
1
nombre es exactamente el nombre o puede ser cualquier caracter? Quiero decir: ¿es una cadena de cuatro caracteres de largo o es un nombre real?
Marco
namePuede ser cualquier secuencia de letras.
czuk
1
posible duplicado de la clasificación natural
Shakti Singh

Respuestas:

256

Esto debería funcionar:

SELECT field,CONVERT(SUBSTRING_INDEX(field,'-',-1),UNSIGNED INTEGER) AS num
FROM table
ORDER BY num;
Marco
fuente
1
¿podría agregar una explicación y un enlace a la documentación?
Angelo Fuchs
Mi cadena es como "name-abc12". Al agregar su código, solo funciona si los caracteres iniciales después de "-" no comienzan con una letra. @Marco ¿Puedes decirme una forma de ignorar las letras sin una condición de dónde?
Eduardo
1
@Eduardo mi consulta debe obtener la cadena después del "-" y convertirla en un número (DEBE ser un número). En su caso, seguiría usando una expresión regular probablemente ...
Marco
La expresión regular de @Marco lo hizo, gracias por el consejo.
Eduardo
32

Puedes usar SUBSTRINGy CONVERT:

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

¿Dónde name_columnestá la columna con los valores "nombre-". El SUBSTRINGelimina todo antes del sexto carácter (es decir, el prefijo "nombre-") y luego CONVERTconvierte el sobrante en un entero real.

ACTUALIZACIÓN : Dadas las circunstancias cambiantes en los comentarios (es decir, el prefijo puede ser cualquier cosa), tendrá que agregar un LOCATEmix:

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

Por supuesto, esto supone que el prefijo no numérico no tiene guiones, pero el comentario relevante dice que:

name puede ser cualquier secuencia de letras

así que debería ser una suposición segura.

mu es demasiado corto
fuente
Respondiendo a mi comentario, nos dijo que el nombre puede ser cualquier secuencia de caracteres, así que no estoy seguro de que pueda usarlo SUBSTRING(name_column, 6). Lo sé, lo publicaste cuando no nos dijo esto ...
Marco
@Marco: Gracias por el aviso, agregué una actualización que debería ocuparse de la nueva información sobre los prefijos. Pero sí, su SUBSTRING_INDEX es más agradable.
mu es demasiado corto
23

Simplemente use CAST,

CAST(column_name AS UNSIGNED)

El tipo para el resultado de conversión puede ser uno de los siguientes valores:

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

Puede usar CAST () para convertir de cadena a int. p.ejSELECT CAST('123' AS INTEGER);

verdesmarald
fuente
15
¿Es esa versión específica? Necesito usarlo SELECT CAST('123' AS SIGNED INTEGER);o SELECT CAST('123' AS UNSIGNED INTEGER);hacerlo funcionar.
Hobo
10
SELECT *, CAST(SUBSTRING_INDEX(field, '-', -1) AS UNSIGNED) as num FROM tableName ORDER BY num;
Gaurav
fuente
1
¿Está seguro de que ORDER BY usa num como número sin usar CONVERT? No estoy seguro, pero puede ser ... Solo me estoy preguntando :)
Marco
4

una forma simple SELECCIONE '123' + 0

VRK RAO
fuente
Aunque este código puede ser de ayuda para resolver el problema, proporcionar un contexto adicional con respecto a por qué y / o cómo responde la pregunta mejoraría significativamente su valor a largo plazo. Por favor, editar su respuesta a añadir un poco de explicación.
Toby Speight
Esto no respondió la pregunta, pero era la respuesta que estaba buscando.
Sagar Shah
su solución es la más elegante y práctica; desafortunadamente no la proporcionó en el contexto de la pregunta con una expresión específica para el ejemplo dado, modifíquela para que sea específica.
chukko
2

Si su clave principal es una cadena en un formato como

ABC / EFG / EE / 13/123 (número de secuencia),
este tipo de cadena se puede usar fácilmente para ordenar con el delimitador ("/")

podemos usar la siguiente consulta para ordenar una tabla con este tipo de clave

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

Una forma genérica de hacer:

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