使用oracle sql自定义排序一系列数字(序列)

时间:2014-01-02 19:23:36

标签: sql oracle

我有一个Table Abstract,其中有一列(SerialNumber)。它的数据如下。

1
1.1
1.1.1
1.1.2
1.2
..
..
10
10.1
10.2

现在,我的要求是根据此列对数据进行排序作为首选项。 SerialNumber中最多可以有2个“点”。

所以1.2.3.4是不可能的。在任何级别的序列中,最大数量可以是999。 即。 999.999.999是最大可能序列。

我尝试发布ORDER BY SerialNumber,就像

1
10
10.1
..
2
2.1

仅仅因为字符排序而不是210来自1。 知道如何实现它。因为我需要在JDBC和多个查询(不同的模块)中使用它,希望尽可能地使用它。

3 个答案:

答案 0 :(得分:3)

我可能会使用正则表达式函数来拆分每个部分以进行排序。类似的东西:

select serialnumber
from data
order by
    to_number(regexp_substr(serialnumber, '[[:digit:]]+')),
    to_number(regexp_substr(serialnumber, '[[:digit:]]+', 1, 2)) nulls first,
    to_number(regexp_substr(serialnumber, '[[:digit:]]+', 1, 3)) nulls first

这将为您提供如下结果:

SERIALNUMBER                                                                    
-------------------------------
1.100                                                                           
1.100.10                                                                        
34.134.819                                                                      
36                                                                              
75.717                                                                          
256.749.864                                                                     
397                                                                             
428.13.647                                                                      
443                                                                             
713.768                                                                         
855.238       

答案 1 :(得分:0)

使用'.'作为分隔符和lpad使用0来提取每个数字的函数。并在order by

中调用函数()
CREATE OR REPLACE FUNCTION FORMAT_MY_SERIAL(
    ORIG_SERIAL VARCHAR2)
  RETURN VARCHAR2
AS
  FINAL_SERIAL VARCHAR2(15) := '';
  SERIAL       VARCHAR2(15);
BEGIN
  SERIAL                   := ORIG_SERIAL;
  WHILE (INSTR(SERIAL,'.') <> 0)
  LOOP
    FINAL_SERIAL := TO_CHAR(SUBSTR(SERIAL,INSTR(SERIAL,'.',-1)+1),'FM099')||'.'||FINAL_SERIAL;
    SERIAL       := SUBSTR(SERIAL,1,INSTR(SERIAL,'.',-1)-1);
  END LOOP;
  FINAL_SERIAL := TRIM(BOTH '.' FROM TO_CHAR(SERIAL,'FM099')||'.'||FINAL_SERIAL);
  RETURN FINAL_SERIAL;
END FORMAT_MY_SERIAL;
/

这是示例

WITH MY_TABLE AS
  ( SELECT '1.1.1' AS SerialNumber FROM dual
  UNION ALL
  SELECT '10' FROM dual
  UNION ALL
  SELECT '1' FROM dual
  UNION ALL
  SELECT '1.2' FROM dual
  UNION ALL
  SELECT '2.1' FROM dual
  UNION ALL
  SELECT '1.10.1' FROM dual
  UNION ALL
  SELECT '2.1' FROM dual
  )
SELECT SerialNumber,
  FORMAT_MY_SERIAL(SerialNumber) as formatted
FROM MY_TABLE
ORDER BY FORMAT_MY_SERIAL(SerialNumber);

<强>结果:

SERIAL FORMATTED
1      001
1.1.1  001.001.001
1.2    001.002
1.10.1 001.010.001
2.1    002.001
2.1    002.001
10     010

答案 2 :(得分:0)

create table temp as select dummy from dual;

alter table temp add  val varchar2(20);

select * from temp;

insert into temp (val) values ('1');
insert into temp (val)values ('1.2');
insert into temp (val)values ('1.1.1');
insert into temp (val)values ('2');
insert into temp (val)values ('2.1');
insert into temp (val)values ('10');

select val
  ,decode(substr(val,1,instr(val,'.')-1),null,val,substr(val,1,instr(val,'.')-1))
from temp
order by     to_number(decode(substr(val,1,instr(val,'.')-1),null,val,substr(val,1,instr(val,'.')-1))),val