Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting varchar field numerically in MySQL

Tags:

sorting

mysql

I have a field number of type varchar. Even though it is of type varchar, it stores integer values with optional leading zeros. A sort orders them lexicographically ("42" comes before "9"). How can I order by numeric values ("9" to come before "42")?

Currently I use the query:

SELECT * FROM table ORDER BY number ASC 
like image 332
wow Avatar asked Jan 14 '11 00:01

wow


People also ask

How do I sort numbers in MySQL?

The ORDER BY keyword is used to sort the result-set in ascending or descending order. The ORDER BY keyword sorts the records in ascending order by default. To sort the records in descending order, use the DESC keyword.

How does MySQL sort string?

Unfortunately, MySQL does not provide any built-in natural sorting syntax or function. The ORDER BY clause sorts strings in a linear fashion i.e., one character a time, starting from the first character.


2 Answers

Try this

SELECT * FROM table_name ORDER BY CAST(field_name as SIGNED INTEGER) ASC 
like image 165
bobs Avatar answered Oct 06 '22 01:10

bobs


There are a few ways to do this:

  1. Store them as numeric values rather than strings. You've already discounted that as you want to keep strings like 00100 intact with the leading zeros.
  2. Order by the strings cast as numeric. This will work but be aware that it's a performance killer for decent sized databases. Per-row functions don't really scale well.
  3. Add a third column which is the numeric equivalent of the string and index on that. Then use an insert/update trigger to ensure it's set correctly whenever the string column changes.

Since the vast majority of databases are read far more often than written, this third option above amortises the cost of the calculation (done at insert/update) over all selects. Your selects will be blindingly fast since they use the numeric column to order (and no per-row functions).

Your inserts and updates will be slower but that's the price you pay and, to be honest, it's well worth paying.

The use of the trigger maintains the ACID properties of the table since the two columns are kept in step. And it's a well-known idiom that you can usually trade off space for time in most performance optimisations.

We've used this "trick" in many situations, such as storing lower-cased versions of surnames alongside the originals (instead of using something like tolower), lengths of identifying strings to find all users with 7-character ones (instead of using len) and so on.

Keep in mind that it's okay to revert from third normal form for performance provided you understand (and mitigate) the consequences.

like image 27
paxdiablo Avatar answered Oct 05 '22 23:10

paxdiablo