递归查找 PostgreSQL 10 层次结构
Recursively look up PostgreSQL 10 hierarchy
我一直在研究递归查询,并且拥有我需要的大部分信息,但在我们的模式中,我们有一个设置可以继承到 parent 的 child。当 child 继承 parent 设置时,它自己的设置被设置为 NULL。这种关系可以跨越多个级别(例如:第 4 个 child 继承自顶部的 parent。
我们正在使用 PostgreSQL 10。
此数据的示例 table 如下所示:
客户(在我们的模式中没有实际的 'inheritance' 列...这只是为了识别那些)
id
name
parent_id
customer_settings
inheritance
2
parent customer A
1
1234501
not inherited
3
child of A sub 1
2
null
inherited
4
child of A sub 2
2
1234502
not inherited
5
child of A2 sub 1
4
null
inherited
6
parent customer B
1
1234503
not inherited
7
child of B sub 1
6
1234504
not inherited
8
child of BS1 sub 1
7
null
inherited
9
child of BS1 sub 2
7
null
inherited
10
child of BS1S2 sub 1
9
null
inherited
这描述了以下层次结构路径:
- parent 客户 A(有自己的 customer_settings)
- child of A sub 1(继承自 'parent customer A')
- child of A sub 2(有自己的 customer_settings)
- child of A2 子 1(继承自 'child of A sub 2')
- parent 客户 B(有自己的 customer_settings)
B 子 1 的 - child(有自己的 customer_settings)
B1S1 子 1 的 - child(继承自 'child of B sub 1')
B1S1 子 2 的 - child(继承自 'child of B sub 1')
- child of BS1S2 sub 1(继承自'child of B sub 1'因为'child of B1S1 sub 2'继承自'child of B sub 1')
我想要做的是创建一个查询,该查询将执行从我的 select 中的当前 child 行到 parent 的反向查找,以便找到第一个 customer_setting 值将被继承,导致结果集看起来更像这样:
客户
id
name
parent_id
customer_settings
inheritance
2
parent customer A
1
1234501
not inherited
3
child of A sub 1
2
1234501
inherited
4
child of A sub 2
2
1234502
not inherited
5
child of A2 sub 1
4
1234502
inherited
6
parent customer B
1
1234503
not inherited
7
child of B sub 1
6
1234504
not inherited
8
child of BS1 sub 1
7
1234504
inherited
9
child of BS1 sub 2
7
1234504
inherited
10
child of BS1S2 sub 1
9
1234504
inherited
在这些层次结构中有许多不同的排列方式,因此继承的级别可能会有所不同。我想说的是最坏的情况,如果必须定义某些东西,那么 10 个级别可能会覆盖它。
我这里的主要问题是弄清楚当该设置为空时如何从上面的 object 中捕获那些 customer_settings。一旦我为每一行设置了该值,我就可以提取其他相关设置,进一步定义每条记录。
我可以递归地查看 向下 table 以收集 parent-child 关系和路径,但我不知道如何查找层次结构以相同的方式。我一直以单个 sub-query 来查看 parent object(例如 sub-query: SELECT customer_setting FROM customers WHERE id = parent_id), 但我似乎无法弄清楚当第一个 find 为 null 时我需要做什么才能查看 up 多个级别。
感谢你们提供的任何帮助。
可以使用递归CTE向上遍历table,然后将CTE加入到原来的table:
with recursive cte(old, id, parent, s) as (
select id, id, parent_id, customer_settings from customers where customer_settings is null
union all
select c.old, c1.id, c1.parent_id, c1.customer_settings from cte c join customers c1 on c.parent = c1.id where c.s is null
)
select c.id, c.name, c.parent_id, case when c.customer_settings is null then c1.s else c.customer_settings end, c.inheritance from customers c left join cte c1 on c.id = c1.old and c1.s is not null;
我一直在研究递归查询,并且拥有我需要的大部分信息,但在我们的模式中,我们有一个设置可以继承到 parent 的 child。当 child 继承 parent 设置时,它自己的设置被设置为 NULL。这种关系可以跨越多个级别(例如:第 4 个 child 继承自顶部的 parent。
我们正在使用 PostgreSQL 10。
此数据的示例 table 如下所示:
客户(在我们的模式中没有实际的 'inheritance' 列...这只是为了识别那些)
id | name | parent_id | customer_settings | inheritance |
---|---|---|---|---|
2 | parent customer A | 1 | 1234501 | not inherited |
3 | child of A sub 1 | 2 | null | inherited |
4 | child of A sub 2 | 2 | 1234502 | not inherited |
5 | child of A2 sub 1 | 4 | null | inherited |
6 | parent customer B | 1 | 1234503 | not inherited |
7 | child of B sub 1 | 6 | 1234504 | not inherited |
8 | child of BS1 sub 1 | 7 | null | inherited |
9 | child of BS1 sub 2 | 7 | null | inherited |
10 | child of BS1S2 sub 1 | 9 | null | inherited |
这描述了以下层次结构路径:
- parent 客户 A(有自己的 customer_settings)
- child of A sub 1(继承自 'parent customer A')
- child of A sub 2(有自己的 customer_settings)
- child of A2 子 1(继承自 'child of A sub 2')
- parent 客户 B(有自己的 customer_settings)
-
B 子 1 的
- child(有自己的 customer_settings)
-
B1S1 子 1 的
- child(继承自 'child of B sub 1') B1S1 子 2 的
- child(继承自 'child of B sub 1')
- child of BS1S2 sub 1(继承自'child of B sub 1'因为'child of B1S1 sub 2'继承自'child of B sub 1')
- child(有自己的 customer_settings)
我想要做的是创建一个查询,该查询将执行从我的 select 中的当前 child 行到 parent 的反向查找,以便找到第一个 customer_setting 值将被继承,导致结果集看起来更像这样:
客户
id | name | parent_id | customer_settings | inheritance |
---|---|---|---|---|
2 | parent customer A | 1 | 1234501 | not inherited |
3 | child of A sub 1 | 2 | 1234501 | inherited |
4 | child of A sub 2 | 2 | 1234502 | not inherited |
5 | child of A2 sub 1 | 4 | 1234502 | inherited |
6 | parent customer B | 1 | 1234503 | not inherited |
7 | child of B sub 1 | 6 | 1234504 | not inherited |
8 | child of BS1 sub 1 | 7 | 1234504 | inherited |
9 | child of BS1 sub 2 | 7 | 1234504 | inherited |
10 | child of BS1S2 sub 1 | 9 | 1234504 | inherited |
在这些层次结构中有许多不同的排列方式,因此继承的级别可能会有所不同。我想说的是最坏的情况,如果必须定义某些东西,那么 10 个级别可能会覆盖它。
我这里的主要问题是弄清楚当该设置为空时如何从上面的 object 中捕获那些 customer_settings。一旦我为每一行设置了该值,我就可以提取其他相关设置,进一步定义每条记录。
我可以递归地查看 向下 table 以收集 parent-child 关系和路径,但我不知道如何查找层次结构以相同的方式。我一直以单个 sub-query 来查看 parent object(例如 sub-query: SELECT customer_setting FROM customers WHERE id = parent_id), 但我似乎无法弄清楚当第一个 find 为 null 时我需要做什么才能查看 up 多个级别。
感谢你们提供的任何帮助。
可以使用递归CTE向上遍历table,然后将CTE加入到原来的table:
with recursive cte(old, id, parent, s) as (
select id, id, parent_id, customer_settings from customers where customer_settings is null
union all
select c.old, c1.id, c1.parent_id, c1.customer_settings from cte c join customers c1 on c.parent = c1.id where c.s is null
)
select c.id, c.name, c.parent_id, case when c.customer_settings is null then c1.s else c.customer_settings end, c.inheritance from customers c left join cte c1 on c.id = c1.old and c1.s is not null;