简体   繁体   English

如何在SQL中按数字排序?

[英]How to sort order by number in SQL?

I am facing a problem to sort order follow the number in the column data in SQL.我在按照 SQL 中列数据中的数字进行排序时遇到问题。 For example, the column data include are 100-1/1/1 ABC , 100-1/1/3 CDE, 100-1/1/2 CDE.例如,列数据包括 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.我想按顺序编号结果进行排序,例如 100-1/1/1 ABC 、100-1/1/2 CDE 和 100-1/1/3 CDE。

Below is sample table data, table name called test2 :下面是示例表数据,表名为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.我使用的是 MySQL 版本,编写的 SQL 查询是SELECT * FROM test2 order by name ,但它无法正确排序数字。

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.谢谢。

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.首先,我们使用regexp_substr(name,'[0-9]+')从字符串中提取排序所需的数字,该数字与第一个数字再匹配一个字符并返回第一次出现,使用regexp_substr(name,'[0-9]+',1,2)第二次出现从另一个数字字符匹配等等......然后在 order by 子句中相应地使用。

Demo 演示

Edit:- Solution for MYSQL older versions编辑:- MYSQL 旧版本的解决方案

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 演示2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM