Sorting varchar field numerically in MySQL - 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

Try this
SELECT * FROM table_name ORDER BY CAST(field_name as SIGNED INTEGER) ASC

There are a few ways to do this:
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.
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.
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.

Actually i've found something interesting:
SELECT * FROM mytable ORDER BY LPAD(LOWER(mycol), 10,0) DESC
This allows you to order the field like:
1
2
3
10
A
A1
B2
10A
111

SELECT * FROM table ORDER BY number + 0

Trick I just learned. Add '+0' to the varchar field order clause:
SELECT * FROM table ORDER BY number+0 ASC
I now see this answer above. I am wondering if this is typecasting the field and an integer. I have not compared performance. Working great.

For a table with values like Er353, ER 280, ER 30, ER36
default sort will give
ER280
ER30
ER353
ER36
SELECT fieldname, SUBSTRING(fieldname, 1, 2) AS bcd,
CONVERT(SUBSTRING(fieldname, 3, 9), UNSIGNED INTEGER) AS num
FROM table_name
ORDER BY bcd, num;
the results will be in this order
ER30
ER36
ER280
ER353

you can get order by according to your requirement my using following sql query
SELECT * FROM mytable ORDER BY ABS(mycol)

given a column username containing VARCHAR's like these:
username1
username10
username100
one could do:
SELECT username,
CONVERT(REPLACE(username, 'username', ''), UNSIGNED INTEGER) AS N
FROM users u
WHERE username LIKE 'username%'
ORDER BY N;
it is not cheap, but does the job.

SELECT * FROM table ORDER BY number ASC
Should display what you want it to display.. looks like you're sorting it by id or number is not defined as integer at the moment.

MySQL ORDER BY Sorting alphanumeric on correct order
example:
SELECT `alphanumericCol` FROM `tableName` ORDER BY
SUBSTR(`alphanumericCol` FROM 1 FOR 1),
LPAD(lower(`alphanumericCol`), 10,0) ASC
output:
0
1
2
11
21
100
101
102
104
S-104A
S-105
S-107
S-111

Another option to keep numerics at a top, then order by alpha.
IF(name + 0, name + 0, 9999999), name

Rough and ready: order by 1*field_name

Related

MySQL returns all rows when field=0 from SECOND Select query

This case is similar to: S.O Question; mySQL returns all rows when field=0, and the Accepted answer was a very simple trick, to souround the ZERO with single quotes
FROM:
SELECT * FROM table WHERE email=0
TO:
SELECT * FROM table WHERE email='0'
However, my case is slightly different in that my Query is something like:
SELECT * FROM table WHERE email=(
SELECT my_column_value FROM myTable WHERE my_column_value=0 AND user_id =15 LIMIT 1 )
Which in a sense, becomes like simply saying: SELECT * FROM table WHERE email=0, but now with a Second Query.
PLEASE NOTE: It is a MUST that I use the SECOND QUERY.
When I tried: SELECT * FROM table WHERE email='( SELECT my_column_value FROM myTable WHERE my_column_value=0 LIMIT 1 )' (Notice the Single Quotes on the second query)
MySql SCREAMED Errors near '(.
How can this be achieved
Any Suggestion is highly honored
EDIT1: For a visual perspective of the Query
See the STEN_TB here: http://snag.gy/Rq8dq.jpg
Now, the main aim is to get the sten_h where rawscore_h = 0;
The CURRENT QUERY as a whole.
SELECT sten_h
FROM sten_tb
WHERE rawscore_h = (
SELECT `for_print_stens_rowscore`
FROM `for_print_stens_tb`
WHERE `for_print_stens_student_id` =3
AND `for_print_stens_factor_name` = 'Factor H' )
The result of the Second Query can be any number including ZERO.
Any number from >=1 Works and returns a single corresponding value from sten_h. Only =0 does not Work, it returns all rows
That's the issue.
CORRECT ANSWER OR SOLUTION FOR THIS
Just in case someone ends up in this paradox, the Accepted answer has it all.
SEE STEN_TB: http://snag.gy/Rq8dq.jpg
SEE The desired Query result here: http://snag.gy/wa4yA.jpg
I believe your issue is with implicit datatype conversions. You can make those datatype conversions explicit, to gain control.
(The "trick" with wrapping a literal 0 in single quotes, that makes the literal a string literal, rather than a numeric.)
In the more general case, you can use a CAST or CONVERT function to explicitly specify a datatype conversion. You can use an expression in place of a column name, wherever you need to...
For example, to get the value returned by my_column_value to match the datatype of the email column, assuming email is character type, something like:
... email = (SELECT CONVERT(my_column_value,CHAR(255)) FROM myTable WHERE ...
or, to get the a literal integer value to be a string value:
... FROM myTable WHERE my_column_value = CONVERT(0,CHAR(30)) ...
If email and my_column_value are just indicating true or false then they should almost certainly be both BIT NOT NULL or other two-value type that your schema uses for booleans. (Your ORM may use a particular one.) Casting is frequently a hack made necessary by a poor design.
If it should be a particular user then you shouldn't use LIMIT because tables are unordered and that doesn't return a particular user. Explain in your question what your query is supposed to return including exactly what you mean by "15th".
(Having all those similar columns is bad design: rawscore_a, sten_a, rawscore_b, sten_b,... . Use a table with two columns: rawscore, sten.)

How to sort the columns in the mysql database

I am having column named rating in the mysql database table with multiple values from 1+,2+,................9+,10+,12+. when i am sorting this column with query
select * from tbl_app order by rating desc
I am getting 9+ as highest value, can any one tell me how to get 12+ as highest value
SELECT rating,SUBSTR(rating,1,LENGTH(rating)-1) FROM tbl_app ORDER BY CAST(SUBSTR(rating,1,LENGTH(rating)-1) as SIGNED) DESC;
if the last char is always a '+',the sql above will work.
what have you kept the datatype of the column rating ? If you have kept it varchar or text then this query will not work for sorting values as per descending order.
Probably the easiest thing to do in MySQL is cast those odd looking strings to numbers:
order by cast(rating as unsigned) desc
-- or less explicitly
order by rating + 0 desc
Both of those casts will stop trying to convert the string to a number when they hit the + so you'll get them sorted numerically.
Simply removing the plus signs from the strings will still leave you with strings and '10' < '2' is just as true for strings as '10+' < '2+'. That's actually your whole problem: you're storing numbers as decorated strings when you should be storing them as integers and adding the + decorations when you display them. You really should fix your schema to make sense instead of adding ugly hacks to work around your schema's strange ideas.
try this :
select convert(replace(rating,'+',' '),unsigned integer) as x from tab order by x desc
sql_fiddle_demo

sql query help in sorting a field that's got both string and numbers

I've got a text field called source_recid. It stores half string half number like strings in it.
Example
shop.orders.32442
the syntax is DATABASENAME.TABLENAME.RECID
My goal is to scan this col and find out the biggest RECID ( the integer) in it.
So, in a case like this
shop.orders.32442
shop.orders.82000
shop.orders.34452
It would be the record whose source_recid is shop.orders.82000. Why? Cause 82000 happens to be the largest integer.
What SQL statement would get me that record?
One option to this is to create a new column ( the_ids ) and move all the integers in it and then run something like this
select source_recid from mytable
where source_recid like 'shop.orders.%'
order by the_ids DESC
LIMIT 1
Is there a way to pull this off without going thru this step?
First of all, unless all of your RECIDs are exactly five characters long forever and always, the select you put up won't work, becuase "shop.order.9" would come out as larger than "shop.order.10", which is wrong.
What I think we need to do here is extract the numeric part, cast it to an integer, and sort by that. Now, I don't have access to mySQL, so this may not be exactly right, but it should be close ...
SELECT
CAST(SUBSTRING_INDEX(RECID,'.',-1) AS INT) AS RecIdNumber
FROM
table
WHERE
RECID LIKE 'shop.order.%'
ORDER BY
RecIdNumber DESC
LIMIT
0, 1
This will take the part after the last dot, convert it to an INT, name it 'RecIdNumber', and sort by that.
I hope this helps.
SELECT CAST(SUBSTRING_INDEX(field,'.',-1) AS INT) AS RID
FROM yourtable
WHERE
RECID LIKE 'shop.order.%'
ORDER BY
RID DESC

Pad middle of string with 0s in mysql ORDER BY clause to respect "true" numeric order

In my admin interface I have a listing of subdomains, which follow following logic:
node-k1
node-k2
node-k3
node-k4
node-k5
node-k6
node-k7
node-k8
node-k9
node-k10
node-k11
These are stored in mysql. I need to list them in numeric order, however since I lack leading 0s after node-k, it orders them like so:
node-k1
node-k10
node-k11
node-k2
node-k3
etc
There nodes have different letters, so node-j_ would appear before node-k_. ORDER BY node ASC works fine with the letters obviously, however the numbers are an annoying issue.
Is there any way to make the ORDER BY clause put them in a right order? This is an admin only function, so performance isn't really an issue.
If the number always starts at character 7, then you can cast it to an integer like this:
SELECT *
FROM tbl
ORDER BY SUBSTR(subdomain, 1, 6), CAST(SUBSTR(subdomain, 7) AS UNSIGNED)
This orders them first by the prefix, then by the number.
in your table of where the nodes were recorded, there must be a numeric field(unique) which basically refers to the order of your nodes.
ID NodeName
1 Node-k1
2 Node-k2
3 Node-k3
4 Node-k10
5 Node-k11
select Nodename from table1 order by ID.
Rhian

mysql sort string number

I have a column of type varchar that stores many different numbers. Say for example there are 3 rows: 17.95, 199.95 and 139.95.How can i sort that field as numbers in mysql
Quickest, simplest? use * 1
select *
from tbl
order by number_as_char * 1
The other reasons for using * 1 are that it can
survive some horrendous mishaps with underflow (reduced decimal precision when choosing what to cast to)
works (and ignores) columns of purely non-numeric data
strips numeric portions of alphanumeric data, such as 123A, 124A, 125A
If you need to sort a char column containing text AND numbers then you can do this.
tbl contains: 2,10,a,c,d,b,4,3
select * from tbl order by number_as_char * 1 asc, number_as_char asc
expected output: 2,3,4,10,a,b,c,d
If you don't add the second order by argument only numbers will be sorted - text actually gets ignored.
Use a CAST or a CONVERT function.
This approach is helpful when sorting text as numbers:
SELECT `my_field`
FROM `my_table`
ORDER BY `my_field` + 0;
Found the solution on http://crodrigues.com/trick-mysql-order-string-as-number/.
Pad the string with leading zeroes:
ORDER BY LPAD(`column`,<max length of string>,"0")
If you really have to you can do this if your source data is compatible:
SELECT column FROM table ORDER BY CAST(column AS DECIMAL(10,2))
It's not going to be very fast for large data sets though. If you can you should change the schema to use DECIMAL in the first place though. Then it can be properly indexed for better performance.