PostgreSQL Oracle 相容性 - connect by 2

weixin_33766168發表於2018-10-05

標籤

PostgreSQL , Oracle , 樹形查詢 , 遞迴 , connect by , tablefunc , connectby


背景

Oracle connect by語法經常用於有樹形關係的記錄查詢,PostgreSQL使用CTE遞迴語法,可以實現同樣的功能。

《PostgreSQL Oracle 相容性之 - connect by 高階選項 CONNECT_BY_ISLEAF、SYS_CONNECT_BY_PATH、CONNECT_BY_ISCYCLE、LEVEL》

《PostgreSQL Oracle 相容性之 - connect by》

本文通過一個更加簡單的方法,同樣可以實現一樣的功能,用到tablefunc外掛中的connectby函式。

介面如下

https://www.postgresql.org/docs/devel/static/tablefunc.html

connectby(text relname, text keyid_fld, text parent_keyid_fld  
          [, text orderby_fld ], text start_with, int max_depth  
          [, text branch_delim ])  
  
setof record	  
  
Produces a representation of a hierarchical tree structure  
Parameter Description
relname Name of the source relation
keyid_fld Name of the key field
parent_keyid_fld Name of the parent-key field
orderby_fld Name of the field to order siblings by (optional)
start_with Key value of the row to start at
max_depth Maximum depth to descend to, or zero for unlimited depth
branch_delim String to separate keys with in branch output (optional)

例子

create extension tablefunc;  
  
CREATE TABLE connectby_tree(keyid text, parent_keyid text, pos int);  
  
INSERT INTO connectby_tree VALUES('row1',NULL, 0);  
INSERT INTO connectby_tree VALUES('row2','row1', 0);  
INSERT INTO connectby_tree VALUES('row3','row1', 0);  
INSERT INTO connectby_tree VALUES('row4','row2', 1);  
INSERT INTO connectby_tree VALUES('row5','row2', 0);  
INSERT INTO connectby_tree VALUES('row6','row4', 0);  
INSERT INTO connectby_tree VALUES('row7','row3', 0);  
INSERT INTO connectby_tree VALUES('row8','row6', 0);  
INSERT INTO connectby_tree VALUES('row9','row5', 0);  
  
-- with branch, without orderby_fld (order of results is not guaranteed)  
SELECT * FROM connectby('connectby_tree', 'keyid', 'parent_keyid', 'row2', 0, '~')  
 AS t(keyid text, parent_keyid text, level int, branch text);  
 keyid | parent_keyid | level |       branch  
-------+--------------+-------+---------------------  
 row2  |              |     0 | row2  
 row4  | row2         |     1 | row2~row4  
 row6  | row4         |     2 | row2~row4~row6  
 row8  | row6         |     3 | row2~row4~row6~row8  
 row5  | row2         |     1 | row2~row5  
 row9  | row5         |     2 | row2~row5~row9  
(6 rows)  
  
-- without branch, without orderby_fld (order of results is not guaranteed)  
SELECT * FROM connectby('connectby_tree', 'keyid', 'parent_keyid', 'row2', 0)  
 AS t(keyid text, parent_keyid text, level int);  
 keyid | parent_keyid | level  
-------+--------------+-------  
 row2  |              |     0  
 row4  | row2         |     1  
 row6  | row4         |     2  
 row8  | row6         |     3  
 row5  | row2         |     1  
 row9  | row5         |     2  
(6 rows)  
  
-- with branch, with orderby_fld (notice that row5 comes before row4)  
SELECT * FROM connectby('connectby_tree', 'keyid', 'parent_keyid', 'pos', 'row2', 0, '~')  
 AS t(keyid text, parent_keyid text, level int, branch text, pos int);  
 keyid | parent_keyid | level |       branch        | pos  
-------+--------------+-------+---------------------+-----  
 row2  |              |     0 | row2                |   1  
 row5  | row2         |     1 | row2~row5           |   2  
 row9  | row5         |     2 | row2~row5~row9      |   3  
 row4  | row2         |     1 | row2~row4           |   4  
 row6  | row4         |     2 | row2~row4~row6      |   5  
 row8  | row6         |     3 | row2~row4~row6~row8 |   6  
(6 rows)  
  
-- without branch, with orderby_fld (notice that row5 comes before row4)  
SELECT * FROM connectby('connectby_tree', 'keyid', 'parent_keyid', 'pos', 'row2', 0)  
 AS t(keyid text, parent_keyid text, level int, pos int);  
 keyid | parent_keyid | level | pos  
-------+--------------+-------+-----  
 row2  |              |     0 |   1  
 row5  | row2         |     1 |   2  
 row9  | row5         |     2 |   3  
 row4  | row2         |     1 |   4  
 row6  | row4         |     2 |   5  
 row8  | row6         |     3 |   6  
(6 rows)  

參考

《PostgreSQL 家譜、族譜類應用實踐 - 圖式關係儲存與搜尋》

《PostgreSQL 遞迴妙用案例 - 分組資料去重與打散》

《PostgreSQL Oracle 相容性之 - INDEX SKIP SCAN (遞迴查詢變態優化) 非驅動列索引掃描優化》

《PostgreSQL 圖式搜尋(graph search)實踐 - 百億級圖譜,毫秒響應》

《[未完待續] AgensGraph 圖資料庫介紹以及 on ECS部署》

《PostgreSQL 實踐 - 內容社群(如論壇)圖式搜尋應用》

《[未完待續] PostgreSQL 圖計算》

《小微貸款、天使投資(風控助手)業務資料庫設計(圖式搜尋\圖譜分析) - 阿里雲RDS PostgreSQL, HybridDB for PostgreSQL最佳實踐》

《PostgrSQL 遞迴SQL的幾個應用 - 極客與正常人的思維》

《PostgreSQL 遞迴查詢CASE - 樹型路徑分組輸出》

《金融風控、公安刑偵、社會關係、人脈分析等需求分析與資料庫實現 - PostgreSQL圖資料庫場景應用》

《用PostgreSQL找回618秒逝去的青春 - 遞迴收斂優化》

《distinct xx和count(distinct xx)的變態遞迴優化方法 - 索引收斂(skip scan)掃描》

《時序資料合併場景加速分析和實現 - 複合索引,視窗分組查詢加速,變態遞迴加速》

《facebook linkbench 測試PostgreSQL社交關係圖譜場景效能》

《PostgreSQL 使用遞迴SQL 找出資料庫物件之間的依賴關係》

《PostgreSQL 遞迴死迴圈案例及解法》

《PostgreSQL 遞迴查詢一例 - 資金累加鏈》

《PostgreSQL Oracle 相容性之 - WITH 遞迴 ( connect by )》

《遞迴優化CASE - group by & distinct tuning case : use WITH RECURSIVE and min() function》

《遞迴優化CASE - performance tuning case :use cursor\trigger\recursive replace (group by and order by) REDUCE needed blockes scan》

《PostgreSQL 樹狀資料儲存與查詢(非遞迴) - Use ltree extension deal tree-like data type》

相關文章