如何使用递归 CTE 找到最终的 "link in the chain"
How do I find the final "link in the chain" using a recursive CTE
我很接近这个但遗漏了一些东西。如何只获取链中的第一个和最后一个链接,例如 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'
这是一种方法:
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
进行过滤。
original_cname | becomes
:------------- | :------
B | E
C | E
D | E
您可以通过仅从链末端而不是所有链接开始递归来实现此目的,然后像您已经在做的那样迭代地预先添加链接:
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)
我很接近这个但遗漏了一些东西。如何只获取链中的第一个和最后一个链接,例如 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'
这是一种方法:
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
进行过滤。
original_cname | becomes :------------- | :------ B | E C | E D | E
您可以通过仅从链末端而不是所有链接开始递归来实现此目的,然后像您已经在做的那样迭代地预先添加链接:
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)