我使用的是 Postgres 15.1,并且有一个
node
表,如下所示:
CREATE TABLE node (
id TEXT PRIMARY KEY,
is_skippable BOOL,
prev TEXT REFERENCES node(id),
"next" TEXT REFERENCES node(id)
);
这个表代表一系列双向链表,但在某些情况下,对于某些查询,我想从列表中删除
is_skippable
节点并链接它们周围。
例如,如果我在数据库中植入了以下数据,其中有一个
A1 <-> A2 <-> A3
的链接列表(带有 A2
可跳过)和 B1 <-> B2
之一:
INSERT INTO node VALUES
('A1', FALSE, NULL, 'A2'),
('A2', TRUE, 'A1', 'A3'),
('A3', FALSE, 'A2', NULL),
('B1', FALSE, NULL, 'B2'),
('B2', FALSE, 'B1', NULL);
对于某些查询,我想链接
is_skippable
节点。因此,如果我查询这个完整的表,我要查找的结果集是:
id | 上一页 | 下一个 |
---|---|---|
A1 | 空 | A3 |
A3 | A1 | 空 |
B1 | 空 | B2 |
B2 | B1 | 空 |
请注意,
A2
不在结果集中,并且A2
的指针已被重写到其前后的节点。
Postgres 中有没有一种得到良好支持的方法来做到这一点?我在 StackOverflow 上的其他地方看到了简单链表的答案(比如postgresql 中的链表概念),但它们不需要重写指针。谢谢!
示例小提琴:https://dbfiddle.uk/4lB4TAtF。
您可能可以将其折叠起来以同时在两个方向上运行横向查询,但这里有一个示例:demo at db<>fiddle
select id,coalesce(
(with recursive cte as(
select n2.prev
from node n2
where n2.id=n1.prev
union
select n2.prev
from node n2 join cte
on n2.id=cte.prev
and is_skippable)
select prev from cte)
,prev) as prev
,coalesce(
(with recursive cte as(
select n2.next
from node n2
where n2.id=n1.next
and n2.is_skippable
union
select n2.next
from node n2 join cte
on n2.id=cte.next
and is_skippable)
select next from cte)
,next) as next
from node n1
where not is_skippable;
id | 上一页 | 下一个 |
---|---|---|
A1 | 空 | A3 |
A3 | A1 | 空 |
B1 | 空 | B2 |
B2 | B1 | 空 |