0

I am facing a problem to sort order follow the number in the column data in SQL. For example, the column data include are 100-1/1/1 ABC , 100-1/1/3 CDE, 100-1/1/2 CDE. I want to sort in order number result follow like 100-1/1/1 ABC ,100-1/1/2 CDE and 100-1/1/3 CDE.

Below is sample table data, table name called test2:

id  |    name          | 
4     200 DAVID
1     100 JOHN
3     100-1 SHAWN
9     100-1/1 PETER
11    100-1/1/1 ALVIS
12    100-1/1/10 ROBERT
2     100-1/1/11 HENRY
13    100-1/1/3 PIRES
14    100-2 CRISTY
20    100-1/2 BILLY
32    100-1/2/1 JIOUS

I am using MySQL version, and write the SQL query is SELECT * FROM test2 order by name, but it cannot sort the number correctly.

Actually I want the expected result is like below the table:

id  |    name          | 
1     100 JOHN
3     100-1 SHAWN
9     100-1/1 PETER
11    100-1/1/1 ALVIS
13    100-1/1/3 PIRES
12    100-1/1/10 ROBERT
2     100-1/1/11 HENRY
20    100-1/2 BILLY
32    100-1/2/1 JIOUS
14    100-2 CRISTY
4     200 DAVID

This is my real scenario for sort the name:

picture

Hope someone can guide me to solve this problem. Thanks.

1 Answers1

1

I am no expert in using regular expression , however using basic one we could achieve it as bellow,

with cte as
(
select '200 DAVID' name
union all
select '100 JOHN'
union all
select '100-1 SHAWN'
union all
select '100-1/1 PETER'
union all
select '100-1/1/1 ALVIS'
union all
select '100-1/1/3 PIRES'
union all
select '100-1/1/10 ROBERT'
union all
select '100-1/1/11 HENRY'
union all
select '100-1/2 BILLY'
union all
select '100-1/2/1 JIOUS'
)
select *
  from(select t.*,cast(regexp_substr(name,'[0-9]+') as unsigned) col1
                 ,cast(regexp_substr(name,'[0-9]+',1,2) as unsigned) col2
                 ,cast(regexp_substr(name,'[0-9]+',1,3) as unsigned) col3
                 ,cast(regexp_substr(name,'[0-9]+',1,4) as unsigned) col4
  from cte t) c
order by col1,col2,col3,col4

First we extract the numeric required for ordering from the string using regexp_substr(name,'[0-9]+') which matches first numeric one more character and returns the first occurrence and with regexp_substr(name,'[0-9]+',1,2) the second occurrence from one more numeric character match and so on...... and then use accordingly in the order by clause.

Demo

Edit:- Solution for MYSQL older versions

select t.id,t.name
from
(
select t.*, cast((case when col1_col2_ref > 0 
                      then 
                        substring_index(modified_name,'-',1)
                  else 
                     modified_name
                  end) as unsigned) col1
          , cast((case when    col1_col2_ref > 0
                           and col3_ref > 0
                       then 
                          substr(modified_name,(col1_col2_ref + 1),(col3_ref - (col1_col2_ref + 1)))
                       when col1_col2_ref > 0
                       then 
                         substr(modified_name,(col1_col2_ref + 1))
                  end) as unsigned) col2
          , cast((case when    col3_ref > 0
                           and col4_ref > 0
                       then 
                         substr(modified_name,(col3_ref + 1),(col4_ref - (col3_ref + 1)))
                       when col3_ref > 0
                       then 
                         substr(modified_name,(col3_ref + 1))
                  end) as unsigned) col3
          , cast((case when col4_ref > 0
                        then 
                         substr(modified_name,(col4_ref + 1))
                   end) as unsigned) col4
  from
(
select t.*,substring_index(name,' ',1) modified_name
          ,locate('-',name,1) col1_col2_ref
          ,locate('/',name,1) col3_ref
          ,locate('/',name,locate('/',name,1)+1) col4_ref
  from test t
) t
) t
order by col1,col2,col3,col4

Demo2

Sujitmohanty30
  • 3,256
  • 2
  • 5
  • 23