问题
I have strings such as M1 M3 M4 M14 M30 M40
etc (really any int 2-3 digits after a letter)
When I do " ORDER BY name " this returns:
M1, M14, M3, M30, M4, M40
When I want:
M1, M3, M4, M14, M30, M40
Its treating the whole thing as a string but I want to treat it as string + int
Any ideas?
回答1:
You could use SUBSTR and CAST AS UNSIGNED/SIGNED within ORDER BY:
SELECT * FROM table_name ORDER BY
SUBSTR(col_name FROM 1 FOR 1),
CAST(SUBSTR(col_name FROM 2) AS UNSIGNED)
回答2:
If there can be multiple characters at the beginning of the string, for example like 'M10', 'MTR10', 'ABCD50', 'JL8', etc...
, you basically have to get the substring of the name from the first position of a number.
Unfortunately MySQL does not support that kind of REGEXP operation (only a boolean value is returned, not the actual match).
You can use this solution to emulate it:
SELECT name
FROM tbl
ORDER BY CASE WHEN ASCII(SUBSTRING(name,1)) BETWEEN 48 AND 57 THEN
CAST(name AS UNSIGNED)
WHEN ASCII(SUBSTRING(name,2)) BETWEEN 48 AND 57 THEN
SUBSTRING(name,1,1)
WHEN ASCII(SUBSTRING(name,3)) BETWEEN 48 AND 57 THEN
SUBSTRING(name,1,2)
WHEN ASCII(SUBSTRING(name,4)) BETWEEN 48 AND 57 THEN
SUBSTRING(name,1,3)
WHEN ASCII(SUBSTRING(name,5)) BETWEEN 48 AND 57 THEN
SUBSTRING(name,1,4)
WHEN ASCII(SUBSTRING(name,6)) BETWEEN 48 AND 57 THEN
SUBSTRING(name,1,5)
WHEN ASCII(SUBSTRING(name,7)) BETWEEN 48 AND 57 THEN
SUBSTRING(name,1,6)
WHEN ASCII(SUBSTRING(name,8)) BETWEEN 48 AND 57 THEN
SUBSTRING(name,1,7)
END,
CASE WHEN ASCII(SUBSTRING(name,1)) BETWEEN 48 AND 57 THEN
CAST(SUBSTRING(name,1) AS UNSIGNED)
WHEN ASCII(SUBSTRING(name,2)) BETWEEN 48 AND 57 THEN
CAST(SUBSTRING(name,2) AS UNSIGNED)
WHEN ASCII(SUBSTRING(name,3)) BETWEEN 48 AND 57 THEN
CAST(SUBSTRING(name,3) AS UNSIGNED)
WHEN ASCII(SUBSTRING(name,4)) BETWEEN 48 AND 57 THEN
CAST(SUBSTRING(name,4) AS UNSIGNED)
WHEN ASCII(SUBSTRING(name,5)) BETWEEN 48 AND 57 THEN
CAST(SUBSTRING(name,5) AS UNSIGNED)
WHEN ASCII(SUBSTRING(name,6)) BETWEEN 48 AND 57 THEN
CAST(SUBSTRING(name,6) AS UNSIGNED)
WHEN ASCII(SUBSTRING(name,7)) BETWEEN 48 AND 57 THEN
CAST(SUBSTRING(name,7) AS UNSIGNED)
WHEN ASCII(SUBSTRING(name,8)) BETWEEN 48 AND 57 THEN
CAST(SUBSTRING(name,8) AS UNSIGNED)
END
This will order by the character part of the string first, then the extracted number part of the string as long as there are <=7 characters at the beginning of the string. If you need more, you can just chain additional WHEN
s to the CASE
statement.
回答3:
I couldn't get this working for my issue which was sorting MLS Numbers like below:
V12345 V1000000 V92832
The problem was V1000000 wasn't being valued higher than the rest even though it's bigger.
Using this solved my problem:
ORDER BY CAST(SUBSTR(col_name FROM 2) AS UNSIGNED) DESC
Just removed the SUBSTR(col_name FROM 1 FOR 1)
回答4:
You can use:
order by name,SUBSTRING(name,1,LENGTH(name)-1)
回答5:
It split number and letters as separately.
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(
SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(col,'1', 1), '2', 1), '3', 1), '4', 1), '5', 1), '6', 1)
, '7', 1), '8', 1), '9', 1), '0', 1) as new_col
FROM table group by new_col;
回答6:
Try remove the character with SUBSTR. Then use ABS to get the absolute value from field:
SELECT * FROM table ORDER BY ABS(SUBSTR(field,1));
来源:https://stackoverflow.com/questions/12097368/mysql-order-by-string-with-numbers