在實際應用中, 樹結構資料的應用是很廣泛的, 如書的目錄結構, 組織部門的分級等!!!!!
如一本書的目錄
| name |
code |
P_code |
| 目錄 |
MULU |
0 |
| 第一章 |
zh_1 |
MULU |
| 第一節 |
ji_1_1 |
zh_1 |
| 第一回 |
hu_1_1_1 |
ji_1_1 |
| 第二回 |
hu_1_1_2 |
ji_1_1 |
| 第三回 |
hu_1_1_3 |
ji_1_1 |
| 第二節 |
ji_1_2 |
zh_1 |
| 第一回 |
hu_1_2_1 |
ji_1_2 |
| 第二回 |
hu_1_2_2 |
ji_1_2 |
| 第三回 |
hu_1_2_3 |
ji_1_2 |
| 第二章 |
zh_2 |
MULU |
| …….. |
|
|
如果我們想要一次統計一些東西, 但是要分 目錄, 章,節,回 ! 相關的東西只和回有直接的關係!
那我們的資料就必須是這樣的
A 對應 第一章第二節第三回, 轉換為: A 第一章, 第二章第二節, 第一章第二節第三回 這樣就行了!!!
oracle 有專門的方法展現樹資料, 這個相對其他類型的資料庫方便很多!!!
select tt.code, tt.name,tt.p_code, code_path,name_path, regexp_substr(code_path,'[^/]+[A-Za-z0-9_]*',1,1) lev1_code, regexp_substr(name_path,'[^/]+[A-Za-z0-9_]*',1,1) lev1_name, regexp_substr(code_path,'[^/]+[A-Za-z0-9_]*',1,2) lev2_code, regexp_substr(name_path,'[^/]+[A-Za-z0-9_]*',1,2) lev2_name, regexp_substr(code_path,'[^/]+[A-Za-z0-9_]*',1,3) lev3_code, regexp_substr(name_path,'[^/]+[A-Za-z0-9_]*',1,3) lev3_name from (select t.*,level,CONNECT_BY_ROOT code as root,CONNECT_BY_ISLEAF , SYS_CONNECT_BY_PATH (code, '/') code_path, SYS_CONNECT_BY_PATH (name, '/') name_pathfrom book_mulu t START WITH p_code='0' CONNECT BY NOCYCLE t.p_code = PRIOR t.code) tt
我這裡是用到了oracle 的connect by 這個文法, 網上很多資料的.
要從樹的上面往下查, 還是樹的下面往上查呢, 這個關鍵字 Prior(優先的) 的位置就是關鍵了!!! 男士女士, 女士優先, 那麼男士 女士prior, 女士佔有prior. 所以, 從樹的上面往下查, 下面的優先, 所以prior 給code; 樹的下面往上查, 上面的優先, prior 給p_code, 這樣就很容易理解了!!! NOCYCLE 是針對環狀迴圈的問題資料的!!!
level, connect_by_root, connect_by_isleaf, CONNECT_BY_ISCYCLE 這四個是connect by 文法中特有的關鍵字, 可能還有其他的, 我暫時不清楚!!!
level 是樹的級數, 從1開始!(這裡的樹指查詢出來的資料樹,該資料樹可能是整棵樹的一部分而已);
connect_by_root 是樹的首節點;
connect_by_isleaf 是指當前節點是否為葉子, 1 是; 0 否;
CONNECT_BY_ISCYCLE 如果在當前行中引用了某個父親節點的內容並在樹中出現了迴圈, 會顯示“1”; 否則就顯示“0”;
sys_connect_by_path 函數, 可能在一些行列轉換的處理中,大家就使用過了, 很好的一個函數, 能把樹的目錄層次串聯起來!!!!
如 SYS_CONNECT_BY_PATH (name, '/') 結果就是: 第一章/第二節/第三回.
有了這些, 我們再對資料進行整合, 在有明確層次樹的情況下, 再結合一些oracle 的字串函數, 就很方便地把層次分列了!