限制递归查询(带有语句)的初始(锚定)值

假设我们执行递归查询以通过树的邻接表获得某个树节点的子代,但仅获得一棵子树就足够了。

作为一个例子,我们将树的邻接表创建为

CREATE TABLE Tree
       (parent INTEGER,child  INTEGER);

INSERT INTO Tree
       VALUES -- (parent -> child)
              (1,2),(1,3),4),(2,5),11),(3,9),(5,6),7),8),(9,10),(11,12);

,然后进行递归查询以获取节点2的子代:

WITH RECURSIVE children_i (parent,child)
AS (
   -- anchor/initial values
   VALUES (NULL,2)
   -- SELECT parent,child FROM Tree WHERE parent = 2 LIMIT 1
   UNION ALL
   -- recursion
   SELECT children_i.child,Tree.child FROM Tree,children_i
   WHERE Tree.parent = children_i.child
   )
SELECT * FROM children_i;

将产生

|2
2|5
2|11
5|6
5|7
5|8
11|12

现在我们如何将上面的查询限制为仅跟随单个子树(仅说2-> 5-> {6,7,8}而不是2-> 11)? 我尝试将LIMIT添加到递归的锚点

WITH RECURSIVE children_i (parent,child)
AS (
   -- anchor/initial values
   SELECT parent,children_i
   WHERE Tree.parent = children_i.child
   )
SELECT * FROM children_i;

但是它会产生语法错误LIMIT clause should come after UNION ALL not before(SQLite 3.16.2)。

如何在SQLite中实现这一目标?

gangnow 回答:限制递归查询(带有语句)的初始(锚定)值

您可以使用LIMIT,但需要将其提取以分隔cte

WITH anchor AS (
  SELECT parent,child
  FROM tree
  WHERE parent = 2
  -- ORDER BY ...
  LIMIT 1
),children_i(parent,child) AS (
  -- anchor/initial values
  SELECT parent,child
  FROM anchor
  UNION ALL
  -- recursion
  SELECT c1.child,t1.child
  FROM tree t1
  JOIN children_i c1
    ON t1.parent = c1.child
)
SELECT * FROM children_i;

db<>fiddle demo

,

您似乎想要的不是路径,而是子树,其根节点(仅)是超级树根的子级之一...

您可以通过使用NOT EXISTS和一个子查询来选择超级树的根子级,以选择该根级的所有子级,这些子级在数值上较小。这样,只有在子项中具有最小值的那个子项才被选中。

WITH RECURSIVE children_i
               (parent,child)
AS (
-- anchor/initial values
SELECT t1.parent,t1.child
       FROM tree t1
       WHERE t1.parent = 2
             AND NOT EXISTS (SELECT *
                                    FROM tree t2
                                    WHERE t2.parent = t1.parent
                                          AND t2.child < t1.child)
UNION ALL
-- recursion
SELECT c1.child,t1.child
       FROM tree t1
            INNER JOIN children_i c1
                       ON t1.parent = c1.child)
SELECT *
       FROM children_i;

db<>fiddle

本文链接:https://www.f2er.com/3127690.html

大家都在问