使用多个小数点(.)对Oracle中的记录进行排序

San*_*non 8 sql sorting oracle decimal-point oracle10g

更新:

ORACLE VERSION 10G

我有一个Oracle如下记录列表,这些记录实际上是各种书籍
的部分.记录以下面的格式生成

[主题].[子主题].[第一级] ....... [最后一级]

Sections
--------
1
7.1
6.2 
7.1
7.4
6.8.3
6.8.2
10
1.1
7.6
6.1
11
8.3
8.5
1.1.2
6.4
6.6
8.4
1.1.6
6.8.1
7.7.1
7.5
7.3
Run Code Online (Sandbox Code Playgroud)

我想订购如下

 1
 1.1
 1.1.2
 1.1.6
 6.2    
 6.4    
 6.5    
 6.6    
 6.7    
 6.8.1    
 6.8.2    
 6.8.3    
 7.2    
 7.3    
 7.4    
 7.5    
 7.6    
 7.7.1    
 7.7.2    
 8.3    
 8.4    
 8.5
 10
Run Code Online (Sandbox Code Playgroud)

但由于该字段不是numeric datatype排序结果,所以这样的东西

1
10
1.1
1.1.2
1.1.6
....
.....
8.5
Run Code Online (Sandbox Code Playgroud)

我怎样才能对它们进行排序 由于多个小数点,我无法将它们转换为数字.

是否有任何功能oracle支持这种分类技术

Vin*_*rat 6

当已知最大深度时,您可以在子部分中拆分该部分:

SQL> SELECT SECTION FROM DATA
  2   ORDER BY to_number(regexp_substr(SECTION, '[^.]+', 1, 1)) NULLS FIRST,
  3            to_number(regexp_substr(SECTION, '[^.]+', 1, 2)) NULLS FIRST,
  4            to_number(regexp_substr(SECTION, '[^.]+', 1, 3)) NULLS FIRST;

SECTION
-------
1
1.1
1.1.2
1.1.6
6.1
6.2
[...]
8.5
10
11
Run Code Online (Sandbox Code Playgroud)

如果子节的最大深度未知(但可能在8位字符数据库上少于几百或在ANSI字符数据库中少于几千),您可以定义一个将不可分类的数字转换为可排序字符的函数:

SQL> CREATE OR REPLACE FUNCTION order_section (p_section VARCHAR2)
  2     RETURN VARCHAR2 IS
  3     l_result VARCHAR2(4000);
  4  BEGIN
  5     FOR i IN 1..regexp_count(p_section, '[^.]+') LOOP
  6        l_result := l_result
  7                    || CASE WHEN i > 1 THEN '.' END
  8                    || CHR(64+regexp_substr(p_section, '[^.]+', 1, i));
  9     END LOOP;
 10     RETURN l_result;
 11  END;
 12  /

Function created

SQL> SELECT SECTION, order_section(SECTION)
  2    FROM DATA
  3   ORDER BY 2;

SECTION ORDER_SECTION(SECTION)
------- -------------------------
1       A
1.1     A.A
1.1.2   A.A.B
1.1.6   A.A.F
6.1     F.A
6.2     F.B
[...]
8.5     H.E
10      J
11      K
Run Code Online (Sandbox Code Playgroud)


Wer*_*eit 2

如果级别数是固定的(例如最多 4 个),您可以使用以下级别:

ORDER BY 
    TO_NUMBER(REGEXP_SUBSTR(Sections, '\d+', 1, 1)) NULLS FIRST, 
    TO_NUMBER(REGEXP_SUBSTR(Sections, '\d+', 1, 2)) NULLS FIRST, 
    TO_NUMBER(REGEXP_SUBSTR(Sections, '\d+', 1, 3)) NULLS FIRST, 
    TO_NUMBER(REGEXP_SUBSTR(Sections, '\d+', 1, 4)) NULLS FIRST
Run Code Online (Sandbox Code Playgroud)