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?

dreftymac
  • 31,404
  • 26
  • 119
  • 182
czuk
  • 6,218
  • 10
  • 36
  • 47

12 Answers12

286

This should work:

SELECT field,CONVERT(SUBSTRING_INDEX(field,'-',-1),UNSIGNED INTEGER) AS num
FROM table
ORDER BY num;
Marco
  • 56,740
  • 14
  • 129
  • 152
  • 1
    could you add an explanation and a link to the documentation? – Angelo Fuchs Jul 03 '17 at 12:37
  • 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 Nov 06 '18 at 13:52
  • 1
    @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... – Marco Nov 06 '18 at 19:42
  • @Marco regular expression did it, thank you for the tip. – Eduardo Nov 08 '18 at 12:29
  • [More info](https://www.w3schools.com/sql/func_mysql_substring_index.asp) on this command – Anchith Acharya Oct 23 '20 at 16:35
  • @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: https://dev.mysql.com/doc/refman/5.7/en/string-functions.html#function_substring-index – perepm Aug 20 '21 at 07:56
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.

mu is too short
  • 426,620
  • 70
  • 833
  • 800
  • 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 May 11 '11 at 07:36
  • @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. – mu is too short May 11 '11 at 07:52
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]
Sibin John Mattappallil
  • 1,739
  • 4
  • 23
  • 37
17

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

verdesmarald
  • 11,646
  • 2
  • 44
  • 60
  • 20
    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. – Hobo Apr 25 '13 at 14:30
10
SELECT *, CAST(SUBSTRING_INDEX(field, '-', -1) AS UNSIGNED) as num FROM tableName ORDER BY num;
Gaurav
  • 28,447
  • 8
  • 50
  • 80
  • 1
    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 :) – Marco May 11 '11 at 07:35
9

one simple way SELECT '123'+ 0

V R K RAO
  • 111
  • 1
  • 4
  • 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. – Toby Speight Jul 04 '16 at 09:57
  • This did not answer the question but it was the answer i was looking for. – Sagar Shah Jul 27 '16 at 10:57
  • 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. – chukko Mar 03 '17 at 13:44
5
cast(REGEXP_REPLACE(NameNumber, '[^0-9]', '') as UNSIGNED)
Jayram Kumar
  • 682
  • 2
  • 16
  • 28
3

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

  • 2
    You need to change 1 to -1. http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_substring-index – Gaurav May 11 '11 at 07:32
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
Harsha
  • 3,548
  • 20
  • 52
  • 75
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;
Obsidian
  • 3,719
  • 8
  • 17
  • 30
-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')),
Gank
  • 4,507
  • 4
  • 49
  • 45
  • 1
    Please add some explanation to your answer such that others can learn from it – Nico Haase Mar 09 '21 at 15:16
  • 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. – Jeff Clayton Aug 31 '21 at 12:38
-5

A generic way to do :

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