159

Is it possible to convert text into a number within MySQL query? I have a column with an identifier that consists a name and a number in the format of "name-number". The column has VARCHAR type. I want to sort the rows according to the number (rows with the same name) but the column is sorted according to do character order, i.e.

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

If I cut off the number, can I convert the 'varchar' number into the 'real' number and use it to sort the rows? I would like to obtain the following order.

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

I cannot represent the number as a separate column.

edited 2011-05-11 9:32

I have found the following solution ... ORDER BY column * 1. If the name will not contain any numbers is it safe to use that solution?

3
  • 1
    name is exactly name or it can be any character? I mean: is it a string four chars long or is a real name? Commented May 11, 2011 at 7:26
  • name can be any sequence of letters. Commented May 11, 2011 at 7:30
  • 1
    possible duplicate of mysql natural sorting Commented May 11, 2011 at 7:39

12 Answers 12

286

This should work:

SELECT field,CONVERT(SUBSTRING_INDEX(field,'-',-1),UNSIGNED INTEGER) AS num
FROM table
ORDER BY num;
Sign up to request clarification or add additional context in comments.

5 Comments

could you add an explanation and a link to the documentation?
My string is like "name-abc12". By adding your code, it only works if the initial characters after "-" not starts with a letter. @Marco Can you tell me a way to ignore the letters without a where condition?
@Eduardo my query is supposed to get the string after the "-" and convert it into a number (it MUST be a number). In your case I'd go on using a regular expression probably...
More info on this command
@Eduardo Marco is using SUBSTRING_INDEX which uses a given separator (- in this case) to split the string in "columns" and return the portion of that separation that you ask for (with the third argument). All details in the documentation: dev.mysql.com/doc/refman/5.7/en/…
37

You can use SUBSTRING and CONVERT:

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

Where name_column is the column with the "name-" values. The SUBSTRING removes everything up before the sixth character (i.e. the "name-" prefix) and then the CONVERT converts the left over to a real integer.

UPDATE: Given the changing circumstances in the comments (i.e. the prefix can be anything), you'll have to throw a LOCATE in the mix:

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

This of course assumes that the non-numeric prefix doesn't have any hyphens in it but the relevant comment says that:

name can be any sequence of letters

so that should be a safe assumption.

2 Comments

Answering my comment, he told us name can be any sequence of chars, so I'm not sure you can use SUBSTRING(name_column, 6). I know, you posted it when he didn't tell us this...
@Marco: Thanks for the heads up, I added an update that should take care of the new information about the prefixes. But yeah, your SUBSTRING_INDEX is nicer.
29

Simply use CAST,

CAST(column_name AS UNSIGNED)

The type for the cast result can be one of the following values:

BINARY[(N)]
CHAR[(N)]
DATE
DATETIME
DECIMAL[(M[,D])]
SIGNED [INTEGER]
TIME
UNSIGNED [INTEGER]

Comments

17

You can use CAST() to convert from string to int. e.g. SELECT CAST('123' AS INTEGER);

1 Comment

Is that version specific? I need to use SELECT CAST('123' AS SIGNED INTEGER); or SELECT CAST('123' AS UNSIGNED INTEGER); to get it to work.
10
SELECT *, CAST(SUBSTRING_INDEX(field, '-', -1) AS UNSIGNED) as num FROM tableName ORDER BY num;

1 Comment

Are you sure that the ORDER BY uses num as a number without using CONVERT? I'm not sure, but it can be.. I'm just asking myself :)
9

one simple way SELECT '123'+ 0

3 Comments

Although this code may be help to solve the problem, providing additional context regarding why and/or how it answers the question would significantly improve its long-term value. Please edit your answer to add some explanation.
This did not answer the question but it was the answer i was looking for.
your solution is the most elegant and practical - unfortunately you didnt provide it in the context of the question with specific expression for given example - please modify it to be specific.
5
cast(REGEXP_REPLACE(NameNumber, '[^0-9]', '') as UNSIGNED)

2 Comments

Exactly what I want :)
It's my fortune, I came out helpful for you.
3

To get number try with SUBSTRING_INDEX(field, '-', 1) then convert.

1 Comment

You need to change 1 to -1. dev.mysql.com/doc/refman/5.0/en/…
2

if your primary key is a string in a format like

ABC/EFG/EE/13/123(sequence number)
this sort of string can be easily used for sorting with the delimiter("/")

we can use the following query to order a table with this type of key

SELECT * FROM `TABLE_NAME` ORDER BY 
CONVERT(REVERSE(SUBSTRING(REVERSE(`key_column_name`), 1, LOCATE('/', REVERSE(`key_column_name`)) - 1)) , UNSIGNED INTEGER) DESC

Comments

0

I found it easier to use regex_replace function to strip off all non numeric values from the field and then sort.

SELECT field , CONVERT(REGEXP_REPLACE(field,'[^0-9]',''),UNSIGNED) AS num FROM your_table ORDER BY num;

Comments

-2
select
    `a`.uuid,
    concat('1',REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(`a`.uuid,'-',''),'b','11'),'c','12'),'d','13'),'e','14'),'f','15'),'a','10')),

2 Comments

Please add some explanation to your answer such that others can learn from it
This one may just be responding to the title of this post - converting text to number (in this case a text uuid string) -- using replace (or pretty much anything else) is generally faster than a regex. This also suggests the idea of using a uuid string as primary key. A plain old autoincrement or perhaps a binary uuid would be faster than conversion to string if that is the goal in this case.
-5

A generic way to do :

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.