Question : MYSQL custom Sorting

I want to do a specific sort

I have this list

TMP123
A1-1
A10-1
A1-3
A20-1
A20-2
A2-1

Is it possible to sort in MYSQL
A1-1
A1-3
A2-1
A10-1
A20-1
A20-2
TMP123

Format always fits into this:
(Char x 1 - 3 )(NUM x1 - 3) '-' (NUM x1)

Any Ideas?

Answer : MYSQL custom Sorting

[ case when instr(t,"-") > 0 then instr(t,"-") else length(t)+1 end ]
InStr()  find the position of the dash, but if it does not exist, we pretend there is one at the end of the string.
The result of this is added as a column in the subquery to refer to continuously.

[ case
  when substr(t,2,1) regexp '[0-9]' then left(t,1)
  when substr(t,3,1) regexp '[0-9]' then left(t,2)
  else left(t,3) end ]
This block checks to see if the 2nd letter is [0-9], if it is, it returns the 1st letter as the branch.
If it is not, it continues to check the 3rd letter.  If the 3rd is, the 1st two make the branch.
Otherwise, the first 3 letters make up the branch.

[ case
  when substr(t,2,1) regexp '[0-9]' then cast(substr(t,2,i-2) as SIGNED)
  when substr(t,3,1) regexp '[0-9]' then cast(substr(t,3,i-3) as SIGNED)
  when substr(t,4,1) regexp '[0-9]' then cast(substr(t,4,i-4) as SIGNED) end ]
CAST( .. as SIGNED) is a way to turn a column/expression into a number. Even though you create columns as int, you cannot cast to int. SIGNED means an int that is positive only.  This is required because substr (part of a string) is a string type, which would order "1" before "20" lexicographically.
regexp is a more advanced form of LIKE matching. Regular expressions is complex in itself, but suffice to know "<string> regexp '[0-9]'" tests whether the string contains a digit.  Because we are testing one single character, it checks whether that single character IS a digit.
The the test for the 2nd part is almost the same as the test for branch.
If 2nd is digit, it starts from position 2, 3rd-> pos 3, 4th->pos 4.
Knowing where the rack number starts, we take as many characters as required by subtracting the start pos from the dash location (i-2,i-3,i-4).

[ cast(substr(t,i+1,length(t)) as SIGNED) ]
The last part is found by starting one position after the dash to the rest of string.

These are used directly in the order by, but you can use them in the select as well or update statement.
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
select *
from
(
select *,
 case
  when substr(t,2,1) regexp '[0-9]' then left(t,1)
  when substr(t,3,1) regexp '[0-9]' then left(t,2)
  else left(t,3) end branch,
 case
  when substr(t,2,1) regexp '[0-9]' then cast(substr(t,2,i-2) as SIGNED)
  when substr(t,3,1) regexp '[0-9]' then cast(substr(t,3,i-3) as SIGNED)
  when substr(t,4,1) regexp '[0-9]' then cast(substr(t,4,i-4) as SIGNED) end rack,
 cast(substr(t,i+1,length(t)) as SIGNED) level
from
(
select t, case when instr(t,"-") > 0 then instr(t,"-") else length(t)+1 end as i
from customsort
) SQ
) SQ2
order by
branch, rack, level
Random Solutions  
 
programming4us programming4us