Oracle / MYSQL:对包含字母数字值的列上的选择查询中的记录进行排序

时间:2013-01-16 16:35:45

标签: mysql sql oracle sorting

我知道这个问题已经以各种形式提出,但我的要求恰好有点不同。

假设我有一个包含以下数据的表:

ID  NAME        VALUE

-----------------------------

1   ABC-2-2     X
2   PQRS-1-3    Y
3   ABC-3-2     Z
4   PQRS-1-4    A
5   PQRS-3-4    B
6   MNO-2-1     C
7   AAA-1       D
8   BBB-2       E
9   CCC-3       F

现在,我期待的输出应该是这样的:

ID  NAME        VALUE

-----------------------------
7   AAA-1       D
2   PQRS-1-3    Y
4   PQRS-1-4    A
8   BBB-2       E
6   MNO-2-1     C
1   ABC-2-2     X
9   CCC-3       F
3   ABC-3-2     Z
5   PQRS-3-4    B

请注意,这不是直接的字母数字排序。相反,忽略第一个“ - ”之前的值,并且字段按名称中第一个“ - ”之后的内容排序。

我对PL / SQL不太熟悉,对此有任何帮助都会受到赞赏。

感谢。

PS:请注意,这应该适用于Oracle和MySQL。

3 个答案:

答案 0 :(得分:2)

对于您的示例,这就足够了(Oracle语法):

ORDER BY SUBSTR(name,4)

如果第一个连字符前的字符数可能不同,则可以这样做(再次使用Oracle语法):

ORDER BY SUBSTR(name,INSTR(name,'-')+1)

但是,如果你有以下代码,那将无效:

AAA-10-1
AAA-8-1
AAA-9-1

并期望AAA-10-1出现在AAA-9-1之后。然后你需要进一步解析它:

ORDER BY LPAD(SUBSTR(name,INSTR(name,'-')+1, INSTR(name,'-',1,2)-INSTR(name,'-')-1),10,'0'),
         LPAD(SUBSTR(name,INSTR(name,'-',1,2)+1),10,'0')

(注意我已经使用LPAD(x,10,'0')将类似'1'的值转换为'0000000001'等等,而不是使用TO_NUMBER,因为如果有任何非数字,这可能会失败你的数据。)

示例:

with data as
(
select 'AAA-1' name from dual
union all
select 'PQR-1-4' name from dual
union all
select 'PQR-1-3' name from dual
union all
select 'AAA-10-10' name from dual
union all
select 'AAA-10-1' name from dual
union all
select 'AAA-9-10' name from dual
union all
select 'AAA-9-1' name from dual
)
select *
from data
ORDER BY LPAD(SUBSTR(name,INSTR(name,'-')+1, INSTR(name,'-',1,2)-INSTR(name,'-')-1),10,'0'),
         LPAD(SUBSTR(name,INSTR(name,'-',1,2)+1),10,'0');

输出:

NAME
---------
PQR-1-3
PQR-1-4
AAA-9-1
AAA-9-10
AAA-10-1
AAA-10-10
AAA-1

如果AAA-1应该首先出现:

ORDER BY LPAD(SUBSTR(name,INSTR(name,'-')+1, INSTR(name||'-','-',1,2)-INSTR(name,'-')-1),10,'0'),
         LPAD(SUBSTR(name,INSTR(name||'-','-',1,2)+1),10,'0') nulls first

答案 1 :(得分:0)

不确定mysql语法,但你可以在oracle中执行此操作:

select * from  <your_table>
order by substr(name, 5)

答案 2 :(得分:0)

在mssql中找到问题的语法是:

select * from mytable order by substring(name,PATINDEX('%-%',name)+1,len(name)-PATINDEX('%-%',name))

SqlFiddle