【问题标题】:How do I find the final "link in the chain" using a recursive CTE如何使用递归 CTE 找到最终的“链中的链接”
【发布时间】:2020-06-24 10:00:11
【问题描述】:

我对此很接近,但缺少一些东西。如何仅获取 A->B、B->C 等链中的第一个和最后一个链接?我如何才能得到 A->C?

CREATE TEMP TABLE IF NOT EXISTS chains (
    cname TEXT PRIMARY KEY,
    becomes TEXT
);

INSERT INTO chains
VALUES
    ('A', NULL),
    ('B', 'C'),
    ('C', 'D'),
    ('D', 'E'),
    ('E', NULL)
;

WITH RECURSIVE
final_link AS (
SELECT
    chains.cname,
    chains.becomes
FROM
    chains

UNION

SELECT
    chains.cname,
    final_link.becomes
FROM
    chains
    INNER JOIN final_link
    ON chains.becomes = final_link.cname
)
SELECT * FROM final_link;

我想要的结果是:

cname | becomes
------|--------
'B'   | 'E'
'C'   | 'E'
'D'   | 'E'

【问题讨论】:

  • 在您的示例chains 中,第一个链接是B->C,最后一个链接是D->E,而不是A->BB->C
  • @Bergi。也许我说得不好。我想要 B->E。我不想要任何中间步骤。然后我想要 C->E 没有任何中间步骤。
  • 啊,整个链条,不是一个特定的环节,我明白了。

标签: sql postgresql select common-table-expression recursive-query


【解决方案1】:

这是一种方法:

with recursive final_link as (
    select cname, becomes, cname original_cname, 0 lvl 
    from chains 
    where becomes is not null
    union all
    select c.cname, c.becomes , f.original_cname, f.lvl + 1
    from chains c
    inner join final_link f on f.becomes = c.cname
    where c.becomes is not null
)
select distinct on (original_cname) original_cname, becomes 
from final_link 
order by original_cname, lvl desc

这个想法是让子查询跟踪起始节点以及树中每个节点的级别。然后,您可以在外部查询中使用distinct on 进行过滤。

Demo on DB Fiddle

original_cname |变成 :------------- | :------ 乙|乙 C |乙 D |乙

【讨论】:

  • 我觉得连关卡都没有必要。
【解决方案2】:

您可以通过仅从链结束而不是所有链接开始递归来实现这一点,然后像您已经在做的那样迭代地预先添加链接:

WITH RECURSIVE final_link AS (
  SELECT cname, becomes
  FROM chains c
  WHERE (SELECT becomes IS NULL FROM chains WHERE cname = c.becomes)
UNION
  SELECT c.cname, fl.becomes
  FROM chains c
  INNER JOIN final_link fl ON c.becomes = fl.cname
)
SELECT * FROM final_link;

(Demo)

【讨论】:

  • 哈。这就是我想要做的。我尝试了几个不同的 where 子句,但并没有完全正确。在这种情况下,您所说的“前置”到底是什么意思?我想我对递归 CTE 如何机械地工作有一些了解。
  • @GregoryArenius "prepending" 指的是您的链接链。递归 CTE 的评估方法是从非递归部分(基本情况)开始,然后迭代地添加到集合中,直到它不再增长。 These 将是步骤
猜你喜欢
  • 2017-01-02
  • 2014-07-18
  • 2018-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多