2016-07-28 62 views
2

我有一個submissions表,它基本上是一個單鏈表。鑑於給定行的id我想返回整個列表,特定行是其中的一部分(並且按照正確的順序)。例如,在下面的表中,如果有ID 2我想要按順序取回行1,2,3,4在PostgreSQL中獲取行的序列(鏈接列表)

(4,3) -> (3,2) -> (2,1) -> (1,null) 

我希望1,2,3,4這裏,是因爲4實質上是列表的頭2屬於我希望在列表中遍歷所有。

http://sqlfiddle.com/#!15/c352e/1

enter image description here

有沒有辦法做到這一點使用PostgreSQL的遞歸CTE?到目前爲止,我有以下但這隻會給我的父母,而不是後代

WITH RECURSIVE "sequence" AS (
    SELECT * FROM submissions WHERE "submissions"."id" = 2 
    UNION ALL SELECT "recursive".* FROM "submissions" "recursive" 
    INNER JOIN "sequence" ON "recursive"."id" = "sequence"."link_id" 
) 

SELECT "sequence"."id" FROM "sequence" 
+0

只是要知道,你能詳細解釋如何使用你的數據從'2'獲得'1,2,3,4'嗎?如果我們從'id = 2'開始:'(2,1) - >(1,null)'...似乎你的查詢是正確的,但是期望是錯誤的。 – Abelisto

+0

@Abelisto我需要能夠在序列中提供任何'id'。所以,如果我提供1,2,3或4我應該得到相同的結果,因爲我基本上想要該行是一部分的整體血統 –

回答

0

在對我的大腦又是一個追求。謝謝。

with recursive r as (
    select *, array[id] as lst from submissions s where id = 6 
    union all 
    select s.*, r.lst || s.id 
    from 
    submissions s inner join 
     r on (s.link_id=r.id or s.id=r.link_id) 
    where (not array[s.id] <@ r.lst) 
) 
select * from r; 
0

這種方法使用你已經想到的。
它增加了另一個塊來計算列表的其餘部分,然後將兩者進行自定義反向排序。

WITH RECURSIVE pathtobottom AS (
-- Get the path from element to bottom list following next element id that matches current link_id 
    SELECT 1 i, -- add fake order column to reverse retrieved records 
    * FROM submissions WHERE submissions.id = 2 
    UNION ALL 
    SELECT pathtobottom.i + 1 i, -- add fake order column to reverse retrieved records 
    recursive.* FROM submissions recursive 
    INNER JOIN pathtobottom ON recursive.id = pathtobottom.link_id 
) 
, pathtotop AS (
-- Get the path from element to top list following previous element link_id that matches current id 
    SELECT 1 i, -- add fake order column to reverse retrieved records 
    * FROM submissions WHERE submissions.id = 2 
    UNION ALL 
    SELECT pathtotop.i + 1 i, -- add fake order column to reverse retrieved records 
    recursive2.* FROM submissions recursive2 
    INNER JOIN pathtotop ON recursive2.link_id = pathtotop.id 
), pathtotoprev as (
-- Reverse path to top using fake 'i' column 
    SELECT pathtotop.id FROM pathtotop order by i desc 
), pathtobottomrev as (
-- Reverse path to bottom using fake 'i' column 
    SELECT pathtobottom.id FROM pathtobottom order by i desc 
) 
-- Elements ordered from bottom to top 
SELECT pathtobottomrev.id FROM pathtobottomrev where id != 2 -- remove element to avoid duplicate 
UNION ALL 
SELECT pathtotop.id FROM pathtotop; 
/* 
-- Elements ordered from top to bottom 
SELECT pathtotoprev.id FROM pathtotoprev 
UNION ALL 
SELECT pathtobottom.id FROM pathtobottom where id != 2; -- remove element to avoid duplicate 
*/