一、最原始的表说明

Sql代码   收藏代码
  1. CREATE TABLE DATADIC  
  2. (  
  3.   DATAID       NUMBER                           NOT NULL,  
  4.   NAME         VARCHAR2(100 BYTE),  
  5.   VALUE        VARCHAR2(100 BYTE),  
  6.   PARENTID     NUMBER,  
  7.   SEQUENCE     NUMBER,  
  8.   DESCRIPTION  VARCHAR2(1000 BYTE)  
  9. )  

 

 datadic 是一张树状的数据字典表,dataId:主键  value:对应的值  parentId:父节点的主键

 使用select * from datadic 查询完数据对应的值如下:

 约定:根的id为0,可以看到根下面有两条记录,分别行业数据,政务数据。

版次及其他版本形式下面有九个子节点,也就是九条根据,分别为3版、1 版、2版……增订本、2版(修订本)

要实现的最终效果是:

   parentID(父节点id)     parentValue(父节点值)    childvalue(子节点值)

        0                                    根                         行业数据*政务数据

      ……                                 ……                        ……

        140                             版次及其他版本形式    3版*1 版*2版……增订本*2版(修订本)

二、取按照parentid分组,组内部按照dataid排序后的行号

Sql代码   收藏代码
  1. select  t.parentid,   
  2.                 t.value,   
  3.                 t.dataid,  
  4.                 (row_number()  /* 按照parentid分组,组内部按照dataid排序后的行号*/  
  5.                  over(partition by parentid order by dataid)  
  6.                 ) numid   
  7.            from datadic t  

查询后的记录集如下:

这个记录表示,parentId为0的记录有6条,numid就是按照parentId分组后按照dataid排序后的rownum.

 

 重点函数:row_number()   over(partition by 分组列 order by 排序列)

还有相关的函数:

      rank() over(partition by 分组列 order by 排序列)   :和名次一样,并列2个之后是第三名

      densrank() over(partition by 分组列 order by 排序列)   :连续顺序,有2个第二名,仍然跟前第三名。

三、按照上面的行号进行轮循,进行组内每行字符串的连接。

Sql代码   收藏代码
  1. select parentid, parentValue,  
  2.         ltrim(sys_connect_by_path(value, '*'), '*') valuues   
  3.    from (select t.parentid,   
  4.                    t.value,   
  5.        t.dataid,  
  6.        parent.VALUE as  parentValue,  
  7.                    (row_number()  /* 按照parentid分组,组内部按照dataid排序后的行号*/  
  8.                       over(partition by t.parentid order by t.dataid)  
  9.                     ) numid   
  10.            from bap_datadic t,bap_datadic parent  
  11.            where t.PARENTID=parent.DATAID  
  12.    )   
  13.    WHERE connect_by_isleaf = 1   
  14.    start with numid = 1   
  15.    connect by numid - 1 = prior numid    and parentid = prior parentid;   

 查询结果如下,可以看到显示父节点id、父节点值、父节点下所有子节点的值。

 

重点函数:sys_connect_by_path(value, '*')

     value表示要连接的字段,‘*’表示连接符。

    使用这个方法之前必须在where条件中构建树

    where start with 条件1  connect by prior 条件2

   条件1 :表示起始条件,例如,起始条件为组内排序后的rownum为1。

   条件2 :表示要连接的下一行与上一行的关系,例如上面第一记录,valuues  对应的值是:“出版行业*版权行业”。那么“版权行业”与“出版行业”之间的关系是:相同的parentId中的numid+1,所以其条件为:

        start with numid = 1 
       connect by numid - 1 = prior numid    and parentid = prior parentid;

其中,prior.列名:代表上一行的列。

 

SYS_CONNECT_BY_PATH :实现将从父节点到当前行内容以“path”或者层次元素列表的形式显示出来

 

CONNECT_BY_ROOT: 它用在列名之前用于返回当前层的根节点

 

connect_by_isleaf:来判断当前行是不是叶子。如 果是叶子就会在伪列中显示“1”,如果不是叶子而是一个分支(例如当前内容是其他行的父亲)就显示“0”。

 

CONNECT_BY_ISCYCLE:Oracle 10g 之前的版本中,如果在你的树中出现了环状循环(如一个孩子节点引用一个父亲节点),Oracle 就会报出一个错误提示:“ ORA-01436: CONNECT BY loop in user data”。如果不删掉对父亲的引用就无法执行查询操作。而在 Oracle 10g 中,只要指定“NOCYCLE”就可以进行任意的查询操作。与这个关键字相关的还有一个伪列——CONNECT_BY_ISCYCLE, 如果在当前行中引用了某个父亲节点的内容并在树中出现了循环,那么该行的伪列中就会显示“1”,否则就显示“0”。

 

 

Sql代码   收藏代码
  1. select temp.CASE_ID,ltrim(max(sys_connect_by_path(temp.name,'//')),'//')  
  2. from   
  3. (   select asso.CASE_ID as CASE_ID,  
  4.            subject.NAME as name,  
  5.           (row_number()  over(partition by asso.CASE_ID order by asso.ID)  ) numid                         
  6.     from IPMS_SUBJECT_CASE_ASSO asso,IPMS_SUBJECT subject  
  7.     where  asso.SUBJECT_ID=subject.ID    
  8. )temp  
  9. start with temp.numid=1  
  10. connect by temp.CASE_ID=prior temp.CASE_ID  
  11. and temp.numid-1=prior temp.numid  
  12. group by temp.CASE_ID  
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐