链表:查询存储在sql表中的链表的第一个和最后一个元素

bn31dyow  于 2021-07-29  发布在  Java
关注(0)|答案(3)|浏览(371)

我有一个sql表,其中的“行”表示链表的元素。例如,我可以有以下记录:

(id, previous_id)
------------------
(1, NULL)
(2, NULL)
(3, 2)
(4, 3)
(5, NULL)
(6, 4)
(7, 5)

此表中有3个列表:

(1,)
(2,3,4,6)
(5,7)

我想找出每个列表的最后一个元素和列表中的元素数。我要查找的查询将输出:

last, len
1, 1
6, 4
7, 2

这在sql中可能吗?

slmsl1lt

slmsl1lt1#

WITH RECURSIVE cte AS (
   SELECT id AS first, id AS last, 1 as len
   FROM   lines
   WHERE  previous_id IS NULL

   UNION ALL
   SELECT c.first, l.id, len + 1
   FROM   cte   c
   JOIN   lines l ON l.previous_id = c.last
   )
SELECT DISTINCT ON (first)
       last, len  -- , first -- also?
FROM   cte
ORDER  BY first, len DESC;

db<>在这里摆弄
精确生成结果。
如果你还想要第一个元素,比如你的标题状态,那是很容易得到的。

pgpifvop

pgpifvop2#

可以使用递归cte:

with recursive cte as (
      select l.previous_id as id, id as last
      from lines l
      where not exists (select 1 from lines l2 where l2.previous_id = l.id)
      union all
      select l.previous_id, cte.last
      from cte join
           lines l
           on cte.id = l.id
     )
select cte.last, count(*)
from cte
group by cte.last;

这是一把小提琴。

xkrw2x1b

xkrw2x1b3#

下面是microsoft sql server 2016 db中的一个实现

WITH chain
 AS (SELECT l.id AS [first], 
            l.id AS [last], 
            1 AS [len]
     FROM lines AS l
     WHERE l.previous_id IS NULL
     UNION ALL
     SELECT c.[first], 
            l.id, 
            c.[len] + 1 AS [len]
     FROM chain AS c
          JOIN lines AS l ON l.previous_id = c.[last]),
 result
 AS (SELECT DISTINCT 
            c.[first], 
            c.[last], 
            c.[len], 
            ROW_NUMBER() OVER(PARTITION BY c.[first] ORDER BY c.[len] DESC) AS rn
     FROM chain as c)
 SELECT r.[first], 
        r.[last], 
        r.[len]
 FROM result AS r
 WHERE r.rn = 1
 ORDER BY r.[first];

相关问题