首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SQL中带有停止条件的递归选择?

SQL中带有停止条件的递归选择?
EN

Stack Overflow用户
提问于 2016-10-05 15:46:55
回答 2查看 1.8K关注 0票数 2

我的表名为element,如下所示:

代码语言:javascript
复制
 id | successor | important
----------------------------
  1 | NULL      | 0
  2 | 4         | 1
  3 | 5         | 0
  4 | 8         | 0
  5 | 6         | 1
  6 | 7         | 0
  7 | NULL      | 0
  8 | 10        | 1
  9 | 10        | 0
 10 | NULL      | 0

我从元素的ID开始,每个元素可能有也可能没有后续的元素。因此,给定任何元素ID,我可以从0..n元素构建一个元素链,具体取决于它的继承者和后继者,等等。

假设我的起始ID是2。这将导致以下链:

代码语言:javascript
复制
2 -> 4 -> 8 -> 10

现在我想问一个问题:一个特定的元素链是否至少包含一个重要的== 1元素?

在伪代码中,在没有必要检查的情况下实现此功能的函数如下所示:

代码语言:javascript
复制
boolean chainIsImportant(element)
{
    if (element.important == 1) {
        return true;
    }

    if (element.successor != NULL) {
        return chainIsImportant(element.successor);
    }

    return false;
}

我想这可以用WITH RECURSIVE实现,对吧?一旦找到一个具有重要== 1的元素,我如何停止递归?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-10-05 15:59:11

这通常是通过聚合相关列并在CTE的递归部分中添加一个联接条件来完成的:

代码语言:javascript
复制
with recursive all_elements as (
  select id, successor, important, array[important] as important_elements
  from elements
  where successor is null
  union all
  select c.id, c.successor, c.important, p.important_elements||c.important
  from elements c
     join all_elements p on c.successor = p.id
  where 1 <> all(p.important_elements)
)
select *
from all_elements;

注意,条件是“翻转”的,因为where子句定义了应该包含的行。

票数 6
EN

Stack Overflow用户

发布于 2016-10-05 16:44:06

代码语言:javascript
复制
CREATE TABLE booltree
        ( id INTEGER NOT NULL PRIMARY KEY
        , successor INTEGER REFERENCES booltree(id)
        , important Boolean NOT NULL
        );

INSERT INTO booltree(id , successor , important) VALUES
  ( 1, NULL     , False)
  ,(2, 4        , True)
  ,(3, 5        , False)
  ,(4, 8        , False)
  ,(5, 6        , True)
  ,(6, 7        , False)
  ,(7, NULL     , False)
  ,(8, 10       , True)
  ,(9, 10       , False)
 ,(10, NULL     , False)
        ;

-- SELECT * FROM booltree;

WITH RECURSIVE rec AS (
        SELECT id, important
        FROM booltree
        WHERE successor IS NULL
        UNION ALL
        SELECT bt.id, GREATEST(rec.important, bt.important) AS important
        FROM booltree bt
        JOIN rec ON bt.successor = rec.id
        )
SELECT id, important
FROM rec
ORDER BY important, id;

结果:

代码语言:javascript
复制
CREATE TABLE
INSERT 0 10
 id | important 
----+-----------
  1 | f
  6 | f
  7 | f
  9 | f
 10 | f
  2 | t
  3 | t
  4 | t
  5 | t
  8 | t
(10 rows)

注意:一旦找到了真正的重要性(基本上,在递归联合中不允许左联接),递归就不能停止,但是如果您正在寻找一个给定的id (或其中的一组),那么也许可以使用它作为开始条件,并向上搜索树。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39878504

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档