【问题标题】:Query furthest children in Adjacency List查询邻接表中最远的孩子
【发布时间】:2013-01-19 17:57:31
【问题描述】:

所以我有一个 SQL 查询来检索邻接列表中给定节点的所有子节点。

WITH    RECURSIVE
        q AS
        (
        SELECT  id, name
        FROM    categories h
        WHERE   id = 11846801
        UNION ALL
        SELECT  hc.id, hc.name
        FROM    q
        JOIN    categories hc
        ON      hc.parent = q.id
        )
SELECT  name
FROM    q

有没有办法修改这个查询以返回我只是节点的底层?我不能只指定一个给定的级别,因为每条路径可能有不同的深度。

【问题讨论】:

  • 再想一想,“底部”级别,所以你的意思是 所有 离开节点或只离开从一开始就具有最长路径的节点。我的答案是第二种解释。
  • 是的,请参阅下面的评论。我想多了这个问题。当它只是找到所有没有指向它的父引用的节点时。大约有一百万零一种方法来解决这个问题。
  • 但你可能想要最快的......
  • 没错,尽管对于我的用例来说,数据库时间中的几毫秒只是运行时间的一小部分。

标签: sql postgresql recursive-query adjacency-list


【解决方案1】:

解读一

“所有离开起点的路径最长的节点。”

一种方法是在下降的过程中计算级别,并且只返回最底层的成员:

WITH RECURSIVE q AS (
   SELECT  id, name, 0 AS lvl
   FROM    categories
   WHERE   id = 11846801

   UNION ALL
   SELECT  c.id, c.name, q.lvl + 1
   FROM    q
   JOIN    categories c ON c.parent = q.id
   )
SELECT  id, name
FROM    q
WHERE   lvl = (SELECT max(lvl) FROM q);

解读2

“所有离开节点。”

WITH RECURSIVE q AS (
   SELECT  id, name, parent
   FROM    categories
   WHERE   id = 11846801

   UNION ALL
   SELECT  c.id, c.name, c.parent
   FROM    q
   JOIN    categories c ON c.parent = q.id
   )
SELECT  id, name
FROM    q
WHERE   NOT EXISTS (SELECT FROM q q1 WHERE q1.parent = q.id);

检查q 应该比检查基表更快 - 除非 q 非常大,在这种情况下,主表上的索引可能会更快。

【讨论】:

    【解决方案2】:

    只是为了迭代Gordon Linoff's answer。他的查询会起作用是个好主意,但前提是没有NULL 值。因此,为了解决这个问题,需要一个额外的 where 子句。

    SELECT id WHERE id NOT IN (SELECT parent FROM categories WHERE parent IS NOT NULL);
    

    我今天才知道这件事。 (并且没有足够的代表发表评论)

    为了符合 SQL 标准,IN 不仅在左侧的表达式为 NULL 时返回 NULL,而且在列表中未找到匹配项且列表中的表达式之一为 NULL 时返回 NULL。

    参考http://dev.mysql.com/doc/refman/5.6/en/comparison-operators.html#function_in

    【讨论】:

      【解决方案3】:

      底层的东西永远不是父母。因此,您可以添加以下where 子句:

      where id not in (select parent from categories)
      

      实际上,在 Postgres 中,not in 可能不是最有效的方法。所以,这可能更有效:

      where not exists (select 1 from categories c where c.parent = q.id)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-17
        • 2017-02-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-25
        • 2016-04-19
        相关资源
        最近更新 更多