【发布时间】:2019-12-18 07:46:15
【问题描述】:
有这样一张桌子
Table "public.access_level"
Column | Type | Modifiers | Storage | Stats target | Description
-----------+---------+-----------+----------+--------------+-------------
uid | uuid | not null | plain | |
parent_id | integer | not null | plain | |
child_id | integer | not null | plain | |
level | integer | not null | plain | |
entity | text | | extended | |
和这样的行(uid 列被删除)
parent_id | child_id | level | entity
-----------+----------+-------+--------
11 | 22 | 4 | a
22 | 33 | 5 | a
33 | 44 | 6 | a
11 | 22 | 7 | b
22 | 33 | 4 | b
33 | 44 | 5 | b
我想要一个输出,它根据每个entity 特有的父母level 的最小值为每一行返回level 值。
这是我想要的输出:
parent_id | child_id | level | entity
-----------+----------+-------+--------
11 | 22 | 4 | a
22 | 33 | 4 | a
33 | 44 | 4 | a
11 | 22 | 7 | b
22 | 33 | 4 | b
33 | 44 | 4 | b
递归方法是可取的,因为层次结构深度不固定。
注意:(parent_id,child_id,entity) 在表中是唯一的
其实 parent_id 和 child_id 是用户。父级为子级授予实体的访问级别。然后,子用户可以为其自己的另一个子用户提供一定级别的访问权限。在某些时候,父母的父母可能会更改其孩子的访问级别。现在所有更深的孩子都必须拥有不超过此的访问级别。无法使用触发器来更新相应的行,因为 parent of parent 可能会回滚更改。
一个场景:
- 11,22,7,b 表示用户 11 将
level的 7 分配给b实体。 - 现在 user-22 在某个时候将 5 的 user-33 级别赋予
b实体 - 然后 user-33 将 user-44 的级别 5 赋予
b实体。 -
重要提示: user-22 将 user-33 的
b访问级别更改为 4您在示例表中看到 -
b实体的 user-33 对 user-44 的访问级别应该在表中保持 5
但我想要一个查询,该查询将为该列返回 4,就好像我对 user-22 的所有级别超过 4 的子级递归地执行它一样。
谢谢
【问题讨论】:
-
听起来你想要的是一个分区:
min(level) over (partition by parent_id)。您可以通过将更多列添加到分区中,将其视为group by。 -
@Viorel,这是无法通过分区实现的。认为每个实体都有一棵树,对于树的每个节点,我想返回最小的
level遍历树到根 -
该级别列使它看起来已经是递归查询的结果,您可以按实体进行分区。数据和所需输出之间的联系对我来说不是很清楚,为什么实体 b 的父级 33 最终的级别为 4,而实体 b 的父级 11 的级别为 7?
-
@Viorel,用更多解释更新了我的答案。
标签: sql postgresql postgresql-11