Oracle connect by语法经常用于有树形关系的记录查询,但是在pg中是不支持这一语法的,不过我们可以使用with recursive语法来实现类似的功能。
除此之外,pg自带的tablefunc插件中的connectby函数也可以达到类似的效果。
使用方法:
connectby(text relname, text keyid_fld, text parent_keyid_fld
[, text orderby_fld ], text start_with, int max_depth
[, text branch_delim ])
参数解释:
使用举例:
安装插件:
bill@bill=>create extension tablefunc ;
CREATE EXTENSION
建表:
bill@bill=>CREATE TABLE connectby_tree(keyid text, parent_keyid text, pos int);
CREATE TABLE
bill@bill=>INSERT INTO connectby_tree VALUES('row1',NULL, 0);
INSERT INTO connectby_tree VALUES('row2','row1', 0);
INSERT 0 1
bill@bill=>INSERT INTO connectby_tree VALUES('row2','row1', 0);
INSERT INTO connectby_tree VALUES('row3','row1', 0);
INSERT 0 1
bill@bill=>INSERT INTO connectby_tree VALUES('row3','row1', 0);
INSERT 0 1
bill@bill=>INSERT INTO connectby_tree VALUES('row4','row2', 1);
INSERT 0 1
bill@bill=>INSERT INTO connectby_tree VALUES('row5','row2', 0);
INSERT INTO connectby_tree VALUES('row6','row4', 0);
INSERT 0 1
bill@bill=>INSERT INTO connectby_tree VALUES('row6','row4', 0);
INSERT 0 1
bill@bill=>INSERT INTO connectby_tree VALUES('row7','row3', 0);
INSERT 0 1
bill@bill=>INSERT INTO connectby_tree VALUES('row8','row6', 0);
INSERT 0 1
bill@bill=>INSERT INTO connectby_tree VALUES('row9','row5', 0);
INSERT 0 1
查询:
1、带有分支,但没有orderby_fld (不保证结果的顺序)
bill@bill=>SELECT * FROM connectby('connectby_tree', 'keyid', 'parent_keyid', 'row2', 0, '~')
bill-# 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)
2、没有分支,也没有orderby_fld (不保证结果的顺序)
bill@bill=>SELECT * FROM connectby('connectby_tree', 'keyid', 'parent_keyid', 'row2', 0)
bill-# 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)
3、有分支,有orderby_fld (注意 row5 在 row4 前面)
bill@bill=>SELECT * FROM connectby('connectby_tree', 'keyid', 'parent_keyid', 'pos', 'row2', 0, '~')
bill-# 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)
4、没有分支,有 orderby_fld(注意 row5 在 row4 前面)
bill@bill=>SELECT * FROM connectby('connectby_tree', 'keyid', 'parent_keyid', 'pos', 'row2', 0)
bill-# 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)