代码之家  ›  专栏  ›  技术社区  ›  danbroooks

在Postgres中实现类似于链表的排序列

  •  1
  • danbroooks  · 技术社区  · 6 年前

    假设我有一个数据库表 teams 有排序列的 position ,位置可以是 null 如果是最后一个结果,或下一个的id team 这个位置比那个队高一个。这将导致一个始终严格排序的列表(如果使用Int,则在插入新的 团队 ,即将它们全部递增1),插入变得不那么复杂。。。

    但要以排序查询的形式检索此表,已证明很棘手,我目前的工作如下:

    WITH RECURSIVE teams AS (  
      SELECT *, 1 as depth FROM team
      UNION
      SELECT t.*, ts.depth + 1 as depth
      FROM team t INNER JOIN teams ts ON ts.order = t.id 
    SELECT
      id, order, depth
    FROM
      teams
    ;
    

    这让我觉得:

     id | order | depth
    ----+-------+-------
     53 |    55 |     1
     55 |    52 |     1
     55 |    52 |     2 
     52 |    54 |     2
     52 |    54 |     3
     54 |       |     3
     54 |       |     4
    

    哪种类型反映了我在排序方面需要达到的程度(最大深度表示我想要的排序…)但是,我无法确定如何更改查询以获得以下内容:

     id | order | depth
    ----+-------+-------
     53 |    55 |     1
     55 |    52 |     2 
     52 |    54 |     3
     54 |       |     4
    

    然而,我似乎改变了它向我抱怨的关于应用 GROUP BY 在两者之间 id depth ... 我怎样才能从现在的我走到我想去的地方?

    1 回复  |  直到 6 年前
        1
  •  3
  •   Abelisto    6 年前

    递归查询应该从某个地方开始(因为现在您要在第一个子查询中选择整个表)。我建议从最后一张唱片开始 order 列为null并遍历到第一条记录:

    with recursive team(id, ord) as (values(53,55),(55,52),(52,54),(54,null)),
      teams as (
        select *, 1 as depth from team where ord is null -- select the last record here
        union all
        select t.*, ts.depth + 1 as depth
        from team t join teams ts on ts.id = t.ord) -- note that the JOIN condition reversed comparing to the original query
    select * from teams order by depth desc; -- finally reverse the order
    
    ┌────┬──────┬───────┐
    │ id │ ord  │ depth │
    ├────┼──────┼───────┤
    │ 53 │   55 │     4 │
    │ 55 │   52 │     3 │
    │ 52 │   54 │     2 │
    │ 54 │ ░░░░ │     1 │
    └────┴──────┴───────┘