标准 SQL 方式(相当于 connect by/prior)使用递归 CTE:
DROP SCHEMA opa CASCADE;
CREATE SCHEMA opa;
SET search_path='opa';
CREATE TABLE parents
( id INTEGER NOT NULL PRIMARY KEY
, zname text
, parent_id INTEGER REFERENCES parents (id)
);
INSERT INTO parents(id,zname,parent_id) VALUES
(1000 , '@', NULL)
,(1200 , 'A', 1000)
,(1201 , 'B', 1000)
,(1202 , 'C', 1000)
,(1203 , 'D', 1000)
,(1204 , 'E', 1200)
,(1205 , 'F', 1200)
,(1206 , 'G', 1201)
,(1207 , 'H', 1205)
,(1208 , 'I', 1205)
,(1209 , 'J', 1205)
;
WITH RECURSIVE zopa AS (
SELECT p0.id AS opa_id, p0.id AS id
, p0.zname AS zname, p0.parent_id AS parent_id
FROM parents p0
WHERE NOT EXISTS (
SELECT * FROM parents nx WHERE nx.id = p0.parent_id)
UNION
SELECT
zp.opa_id AS opa_id
, p1.id AS id
, p1.zname AS zname
, p1.parent_id AS parent_id
FROM parents p1
JOIN zopa zp ON zp.id = p1.parent_id
)
select *
FROM zopa ct
WHERE ct.opa_id = 1000
;
结果:
NOTICE: drop cascades to table opa.parents
DROP SCHEMA
CREATE SCHEMA
SET
NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "parents_pkey" for table "parents"
CREATE TABLE
INSERT 0 11
opa_id | id | zname | parent_id
--------+------+-------+-----------
1000 | 1000 | @ |
1000 | 1202 | C | 1000
1000 | 1200 | A | 1000
1000 | 1201 | B | 1000
1000 | 1203 | D | 1000
1000 | 1205 | F | 1200
1000 | 1204 | E | 1200
1000 | 1206 | G | 1201
1000 | 1209 | J | 1205
1000 | 1207 | H | 1205
1000 | 1208 | I | 1205
(11 rows)