使用SYS_CONNECT_BY_PATH聚合值

时间:2016-12-06 18:59:38

标签: oracle hierarchical-data

我想生成一个数据层次结构。

此查询:

select  connect_by_root(parent_id) as root_id
        ,ID, NAME
        ,SYS_CONNECT_BY_PATH(PARENT_ID,'/') PATH
        ,level
        ,line
        ,LINE*power(10,-level+1) CALC
        ,ltrim(SYS_CONNECT_BY_PATH(lpad(LINE,3,'0'), '.'),'.')  SORT
from    (

  select 3 ID, 1 LINE, 2 PARENT_ID FROM DUAL
  union all
  select 4 ID, 2 LINE, 2 PARENT_ID FROM DUAL
  union all
  select 5 ID, 3 LINE, 2 PARENT_ID FROM DUAL
  union all
  select 6 ID, 1 LINE, 5 PARENT_ID FROM DUAL
  union all
  select 7 ID, 1 LINE, 6 PARENT_ID FROM DUAL

) v
start with v.parent_id = 2
connect by nocycle prior id=parent_id

生成:

ROOT_ID ID PATH     LEVEL   LINE    CALC    SORT
2       3   /2      1       1       1       001
2       4   /2      1       2       2       002
2       5   /2      1       3       3       003
2       6   /2/5    2       1       0.1     003.001
2       7   /2/5/6  3       1       0.01    003.001.001

我想要的是什么:

ROOT_ID ID PATH     LEVEL   LINE    CALC    
2       3   /2      1       1       1       
2       4   /2      1       2       2       
2       5   /2      1       3       3       
2       6   /2/5    2       1       3.1     
2       7   /2/5/6  3       1       3.11

有没有办法让sys_connect_by_path(或其他函数)统一CALC列及其父级?

目前,我正在使用SORT字段来排序行;我宁愿按适当的数值(CALC字段)排序。

2 个答案:

答案 0 :(得分:1)

试试这个:

select  connect_by_root(parent_id) as root_id
        ,ID
        ,SYS_CONNECT_BY_PATH(PARENT_ID,'/') PATH
        ,level
        ,line
        ,LINE*power(10,-level+1) CALC
        ,XMLCAST(XMLQUERY(ltrim(SYS_CONNECT_BY_PATH(LINE*power(10,-level+1), '+'),'+') RETURNING CONTENT) AS NUMBER) SORT
from    (

  select 3 ID, 1 LINE, 2 PARENT_ID FROM DUAL
  union all
  select 4 ID, 2 LINE, 2 PARENT_ID FROM DUAL
  union all
  select 5 ID, 3 LINE, 2 PARENT_ID FROM DUAL
  union all
  select 6 ID, 1 LINE, 5 PARENT_ID FROM DUAL
  union all
  select 7 ID, 1 LINE, 6 PARENT_ID FROM DUAL

) v
start with v.parent_id = 2
connect by nocycle prior id=parent_id

答案 1 :(得分:1)

您可以使用SORT列,然后在一些信息之后(将第一个点更改为逗号并删除其他点)将结果转换为数字。

关键部分在这里

 to_number(regexp_replace(regexp_replace(SORT,'\.',',',1,1),'\.',null),
   '99D9999' , ' NLS_NUMERIC_CHARACTERS = '',.'' ') sort2

实施例 3.1.1 - > 3,1.1 - > 3,11并转换为数字

这里的完整查询

with v as (
  select 3 ID, 1 LINE, 2 PARENT_ID FROM DUAL
  union all
  select 4 ID, 2 LINE, 2 PARENT_ID FROM DUAL
  union all
  select 5 ID, 3 LINE, 2 PARENT_ID FROM DUAL
  union all
  select 6 ID, 1 LINE, 5 PARENT_ID FROM DUAL
  union all
  select 7 ID, 1 LINE, 6 PARENT_ID FROM DUAL

), v2 as (
select  connect_by_root(parent_id) as root_id
        ,ID 
        ,SYS_CONNECT_BY_PATH(PARENT_ID,'/') PATH
        ,level my_level
        ,line
        ,LINE*power(10,-level+1) CALC
        ,ltrim(SYS_CONNECT_BY_PATH( LINE , '.'),'.')  SORT
from     v
start with v.parent_id = 2
connect by nocycle prior id=parent_id
)
select ROOT_ID, ID, PATH, my_level, LINE, CALC, SORT,
to_number(regexp_replace(regexp_replace(SORT,'\.',',',1,1),'\.',null),'99D9999' , ' NLS_NUMERIC_CHARACTERS = '',.'' ') sort2
from v2