SELECT column_list
FROM table_name
START WITH root_condition -- 根節點條件
CONNECT BY PRIOR parent_key = child_key; -- 父子關聯
START WITH:指定根節點(如 super IS NULL 表示頂層主管)。CONNECT BY PRIOR:定義遞歸關聯,PRIOR 修飾父層欄位。LEVEL:根節點為 1,每遞歸一層 +1。SYS_CONNECT_BY_PATH(col, '/'):從根到當前節點的路徑串聯。SELECT LPAD(' ', 4*(LEVEL-1)) || ename AS name, job, empno, mgr
FROM emp
START WITH mgr IS NULL
CONNECT BY PRIOR empno = mgr;
輸出:縮排顯示層級關係,直觀呈現管理鏈。
NO NAME
001 a01
001 a02
001 a03
002 b01
003 c01
003 c02
...
NO RESULT
001 a01;a02;a03
002 b01
003 c01;c02
...
ROW_NUMBER() OVER (ORDER BY no, name DESC),同組內按 NAME 降序,確保葉節點在前。LEAD(rn) OVER (PARTITION BY no ORDER BY rn),取同組下一筆 RN 作為父節點。START WITH rn1 IS NULL CONNECT BY rn1 = PRIOR rn,從最後一筆(根)向前遞歸。MAX(SYS_CONNECT_BY_PATH(name, ';')) 即為完整聚合字串。SELECT no, MAX(SYS_CONNECT_BY_PATH(name, ';')) AS result
FROM (
SELECT no, name, rn, LEAD(rn) OVER (PARTITION BY no ORDER BY rn) AS rn1
FROM (
SELECT no, name, ROW_NUMBER() OVER (ORDER BY no, name DESC) AS rn
FROM a_example2
)
)
START WITH rn1 IS NULL
CONNECT BY rn1 = PRIOR rn
GROUP BY no;
SELECT no, LISTAGG(name, ';') WITHIN GROUP (ORDER BY name) AS result
FROM a_example2
GROUP BY no;
優勢:語法簡潔、效能優於遞歸、支援 ON OVERFLOW TRUNCATE 防止超長字串報錯(ORA-01489)。
| 場景 | 建議方案 | 注意事項 |
|---|---|---|
| 組織架構、BOM 展開 | CONNECT BY | 確保父子鍵有索引;避免循環引用(NOCYCLE) |
| 同群組字串聚合 | 12c+ LISTAGG / 11g XMLAGG | 舊版本用虛擬樹技巧;留意 4000 字元限制 |
| 深度遞歸 > 1000 層 | PL/SQL 迴圈或遞歸 CTE | CONNECT BY 可能觸發 ORA-01436 |
Oracle 階層查詢以 CONNECT BY 為核心,配合 SYS_CONNECT_BY_PATH 可解決字串聚合、路徑顯示等進階需求。12c 起 LISTAGG 成為聚合首選,但理解虛擬樹構造思維對維護舊系統、跨版本相容仍具高價值。