我试图建立"设置"的层次结构,其中值在根级别定义,并且可以被更具体的子级覆盖。如果孩子没有指定值,则应使用其父值。
我将使用一个陈旧的例子来说明问题。这里的层次结构只有三个级别,但我想要一个适用于N级的解决方案。
鉴于我存储的信息如下:
id| parent_id| setting
----------------------
1| NULL| false
2| 1| true
3| 2| NULL
从程序角度来看,我想要的是在树中获取子节点以及它的"设置" value为NULL,以递归方式查看其父级的值,直到找到值或达到根。基本上,对于提供的信息,我想生成以下集合,因此我可以附加一个简单的WHERE
子句来获取任何给定id
的适用设置。
id| setting
-----------
1| false
2| true
3| true
我的观点是“平坦的”#34;祖先和后代的层次结构:
ancestor| descendant| ancestor_setting| descendant_setting
----------------------------------------------------------
1| 2| false| true
1| 3| false| NULL
2| 3| true| NULL
NULL| 1| NULL| false
NULL| 2| NULL| true
NULL| 3| NULL| NULL
通过这种方式,您可以将层次结构的所有级别都作为一个集合进行查询,我希望这对于获得答案非常有用。
到目前为止,我只能选择一个"分支"使用此视图从树中获取:
SELECT COALESCE(ancestor, descendent) id,
CASE WHEN ancestor IS NULL THEN descendant_setting
ELSE ancestor_setting
END setting
FROM hierarchy
WHERE descendant = 3
id| setting
-----------
1| false
2| true
3| NULL
我试图想办法使用这个"扁平"结构形成一组简单的连接,虽然我可以用这种方式获取所有记录(然后在客户端上以程序方式过滤它们),但我想知道是否有方法生成预期的集合以便我可以取回单个ID的预期设置。
答案 0 :(得分:3)
WITH RECURSIVE
q AS
(
SELECT id, parent_id, id ancestor_id, setting
FROM mytable
WHERE parent_id IS NULL
UNION ALL
SELECT m.id, q.id, ancestor_id, COALESCE(m.setting, q.setting)
FROM q
LEFT JOIN
mytable m
ON m.parent_id = q.id
WHERE q.id IS NOT NULL
)
SELECT *
FROM q
WHERE id IS NULL