【问题标题】:Climbing a Parent/Child Database Relationship in Postgres在 Postgres 中爬取父/子数据库关系
【发布时间】:2010-10-05 11:57:26
【问题描述】:

我们有以下示例表(实际上取自 stackoverflow 上的另一个示例...)

CREATE TABLE example (
  id integer primary key,
  name char(200),
  parentid integer,
  value integer);

给定一个特定的孩子,我们希望获得最高的父母。

我知道 tablefunc connectby 函数,但那是为了得到父母的孩子。

但是,我对另一个方向感兴趣,给一个孩子,它的最高父母是什么?我会尝试使用什么类型的查询?

感谢任何友好的建议。

【问题讨论】:

    标签: sql postgresql recursion


    【解决方案1】:

    根据我的经验,SQL 不太擅长这种查询(递归)。我建议创建一个带有 id 和最高父 id 的附加表。当您添加更多子代时,您只需查找其父代的最高父代 ID 并在附加表中插入适当的行。

    您还可以将顶部父 ID 存储在原始表中。

    【讨论】:

    • 这种非规范化可能非常危险,因为值与现实不同步。
    • @Tom H 非规范化通常很危险......这是我们只在其他维度需要时才这样做的主要原因之一(例如递归太慢)
    【解决方案2】:

    您可以编写一个 PL/PgSQL 函数来执行递归:

    CREATE LANGUAGE plpgsql;
    CREATE OR REPLACE FUNCTION get_top_parent(
            child integer
    ) RETURNS integer as $$
    DECLARE
            parent integer;
            last_parent integer;
    BEGIN
            last_parent := child;
            SELECT INTO parent parentid
            FROM example
            WHERE id = child;
    
            IF parent is NOT NULL THEN
                    parent := get_top_parent(parent);
            ELSE
                    parent := last_parent;
            END IF;
            RETURN parent;
    END
    $$ LANGUAGE plpgsql;
    

    这个功能绝对可以优化。如果深度很高并且表很大,它可能会很慢,所以就像 Jegern 提到的那样,缓存层次结构可能是值得的,可能使用触发器等。

    【讨论】:

    • 我认为目前使用递归查询效果最好。我对使用触发器感到紧张,我不相信我们的数据会有很深的层次结构。
    【解决方案3】:

    查看 Joe Celko 的书籍 SQL for Smarties 和他在 Trees and Hierarchies 上的书籍。他在 SQL for Smarties 中有一两节关于树和层次结构的内容,或者如果你想真正深入了解它,那么你可以得到另一本书。 Smarties 的 SQL 还将涉及许多其他数据库设计和查询信息。里面有一些非常好的东西。他提出了建模树的替代方法,这些方法比您使用的邻接表模型效果更好。

    在他的一个模型中,“谁是最高的父母”这个问题变得非常琐碎。

    【讨论】:

    • 我已将这些书添加到我的亚马逊愿望清单中。但是,我对这张表的设计方式没有太多控制权。
    【解决方案4】:

    您可以考虑使用"ltree" contrib 模块。

    【讨论】:

    • ltree 模块看起来不错,但在我看来它更像是文本/字符串分层数据。
    【解决方案5】:

    从 PostgreSQL 8.4 开始使用递归?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-13
      • 1970-01-01
      • 1970-01-01
      • 2021-04-21
      • 2014-10-24
      • 1970-01-01
      相关资源
      最近更新 更多