跳过DLL中某些类型的节点

问题描述 投票:0回答:1

我使用的是 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

postgresql postgresql-15
1个回答
0
投票

您可能可以将其折叠起来以同时在两个方向上运行横向查询,但这里有一个示例: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
© www.soinside.com 2019 - 2024. All rights reserved.