PostgreSQLOracle相容性-connectby2

德哥發表於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 rigger
ecursive replace (group by and order by) REDUCE needed blockes scan》

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


相關文章