从层次结构中的根获取最远的值

时间:2015-06-30 20:22:31

标签: sql postgresql

我试图建立"设置"的层次结构,其中值在根级别定义,并且可以被更具体的子级覆盖。如果孩子没有指定值,则应使用其父值。

我将使用一个陈旧的例子来说明问题。这里的层次结构只有三个级别,但我想要一个适用于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的预期设置。

1 个答案:

答案 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