PostgreSQL:递归加入第二个 table
PostgreSQL: recursively join a second table
我正在努力解决 PostgreSQL 中的递归问题。我需要加入第一个 table 和第二个 table,然后在第二个 table 中递归加入。我看了很多例子,但大多数都是关于在单个 table 中查找父记录,这让我非常困惑。
这是一个包含 tables thing
和 category
的最小示例。 thing
中的记录可能有也可能没有类别:
id
name
category
1
a5
3
2
passat
2
3
apple
NULL
category
中的记录可能在同一个 table 中有一个或多个父项:
id
name
parent_category
1
vehicle
NULL
2
car
1
3
coupe
2
我要查找的结果是所有事物及其类别的组合,以及类别级别(1 为直接父级,2 为以上级别)。
thing_name
category_name
level
a5
coupe
1
a5
car
2
a5
vehicle
3
passat
car
1
passat
vehicle
2
apple
NULL
NULL
我这里有一个数据库 Fiddle:https://www.db-fiddle.com/f/b7V8ddragZZ9x2RsMkdFYn/5
CREATE TABLE category (
id INT,
name TEXT,
parent_category INT
);
INSERT INTO category VALUES (1, 'vehicle', null);
INSERT INTO category VALUES (2, 'car', 1);
INSERT INTO category VALUES (3, 'coupe', 2);
CREATE TABLE thing (
id INT,
name TEXT,
category INT
);
INSERT INTO thing VALUES (1, 'a5', 3);
INSERT INTO thing VALUES (2, 'passat', 2);
INSERT INTO thing VALUES (3, 'apple', null);
使用 CTE 连接表,为您提供组合的树状视图 thing_categories,然后您可以将其与普通递归 CTE 一起使用。
with recursive join_thing_category as (
select thing.id as thing_id,
thing.name as thing_name,
thing.category as thing_category,
category.id as category_id,
category.name as category_name,
category.parent_category as parent_category
from thing left join category on thing.category=category.id
),
recursive_part(n) as (
select thing_id, thing_name, thing_category, category_id, category_name, parent_category, (0*parent_category) + 1 as level from join_thing_category
union all
select 1, thing_name, thing_category, cat.id category_id, cat.name, cat.parent_category as parent, level+1 as level from recursive_part rp cross join category cat
where cat.id=rp.parent_category
)
select thing_name, category_name, level from recursive_part order by 1, 2, 3 limit 1024;
thing_name
category_name
level
a5
car
2
a5
coupe
1
a5
vehicle
3
apple
passat
car
1
passat
vehicle
2
(0*parent_category) + 1 as level
位是为了让没有类别的事物的级别为 NULL 而不是 1。
我正在努力解决 PostgreSQL 中的递归问题。我需要加入第一个 table 和第二个 table,然后在第二个 table 中递归加入。我看了很多例子,但大多数都是关于在单个 table 中查找父记录,这让我非常困惑。
这是一个包含 tables thing
和 category
的最小示例。 thing
中的记录可能有也可能没有类别:
id | name | category |
---|---|---|
1 | a5 | 3 |
2 | passat | 2 |
3 | apple | NULL |
category
中的记录可能在同一个 table 中有一个或多个父项:
id | name | parent_category |
---|---|---|
1 | vehicle | NULL |
2 | car | 1 |
3 | coupe | 2 |
我要查找的结果是所有事物及其类别的组合,以及类别级别(1 为直接父级,2 为以上级别)。
thing_name | category_name | level |
---|---|---|
a5 | coupe | 1 |
a5 | car | 2 |
a5 | vehicle | 3 |
passat | car | 1 |
passat | vehicle | 2 |
apple | NULL | NULL |
我这里有一个数据库 Fiddle:https://www.db-fiddle.com/f/b7V8ddragZZ9x2RsMkdFYn/5
CREATE TABLE category (
id INT,
name TEXT,
parent_category INT
);
INSERT INTO category VALUES (1, 'vehicle', null);
INSERT INTO category VALUES (2, 'car', 1);
INSERT INTO category VALUES (3, 'coupe', 2);
CREATE TABLE thing (
id INT,
name TEXT,
category INT
);
INSERT INTO thing VALUES (1, 'a5', 3);
INSERT INTO thing VALUES (2, 'passat', 2);
INSERT INTO thing VALUES (3, 'apple', null);
使用 CTE 连接表,为您提供组合的树状视图 thing_categories,然后您可以将其与普通递归 CTE 一起使用。
with recursive join_thing_category as (
select thing.id as thing_id,
thing.name as thing_name,
thing.category as thing_category,
category.id as category_id,
category.name as category_name,
category.parent_category as parent_category
from thing left join category on thing.category=category.id
),
recursive_part(n) as (
select thing_id, thing_name, thing_category, category_id, category_name, parent_category, (0*parent_category) + 1 as level from join_thing_category
union all
select 1, thing_name, thing_category, cat.id category_id, cat.name, cat.parent_category as parent, level+1 as level from recursive_part rp cross join category cat
where cat.id=rp.parent_category
)
select thing_name, category_name, level from recursive_part order by 1, 2, 3 limit 1024;
thing_name | category_name | level |
---|---|---|
a5 | car | 2 |
a5 | coupe | 1 |
a5 | vehicle | 3 |
apple | ||
passat | car | 1 |
passat | vehicle | 2 |
(0*parent_category) + 1 as level
位是为了让没有类别的事物的级别为 NULL 而不是 1。