oracle中使用sys_connect_by_path进行表中行值连接
一、最原始的表說明
CREATE TABLE DATADIC (DATAID NUMBER NOT NULL,NAME VARCHAR2(100 BYTE),VALUE VARCHAR2(100 BYTE),PARENTID NUMBER,SEQUENCE NUMBER,DESCRIPTION VARCHAR2(1000 BYTE) )?
?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排序后的行號
select t.parentid, t.value, t.dataid,(row_number() /* 按照parentid分組,組內部按照dataid排序后的行號*/over(partition by parentid order by dataid)) numid 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個第二名,仍然跟前第三名。
三、按照上面的行號進行輪循,進行組內每行字符串的連接。
select parentid, parentValue,ltrim(sys_connect_by_path(value, '*'), '*') valuues from (select t.parentid, t.value, t.dataid,parent.VALUE as parentValue,(row_number() /* 按照parentid分組,組內部按照dataid排序后的行號*/over(partition by t.parentid order by t.dataid)) numid from bap_datadic t,bap_datadic parentwhere t.PARENTID=parent.DATAID) WHERE connect_by_isleaf = 1 start with numid = 1 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”。
?
?
select temp.CASE_ID,ltrim(max(sys_connect_by_path(temp.name,'//')),'//')from ( select asso.CASE_ID as CASE_ID,subject.NAME as name,(row_number() over(partition by asso.CASE_ID order by asso.ID) ) numid from IPMS_SUBJECT_CASE_ASSO asso,IPMS_SUBJECT subjectwhere asso.SUBJECT_ID=subject.ID )tempstart with temp.numid=1connect by temp.CASE_ID=prior temp.CASE_IDand temp.numid-1=prior temp.numidgroup by temp.CASE_ID?
總結
以上是生活随笔為你收集整理的oracle中使用sys_connect_by_path进行表中行值连接的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: freemarker元素的属性为空
- 下一篇: Eclipse配置工程自动执行ant实现