2016-03-28 19 views
1

我在PostgreSQL中有一個由2列,第一個ID和第二個ID組成的表。其中的每個條目都意味着第一個ID和第二個ID之間存在關聯,並且可以保證第一個ID始終大於第二個ID。在PostgreSQL中創建最佳圖形關係

我的目標是處理該表,以便它可以檢測網絡(多個ID相互關聯),並更改表中該網絡的每個關係,以便第一個ID是網絡中的大ID,而第二個ID始終是網絡中最小的ID。
例子:

D->C , C->B , B->A , F->E , H->G 

將變爲:

D->A , C->A , B->A , F->E , H->G 

又如:

D->C , D->B , D->A 

將變爲:

D->A , C->A , B->A 

如何做到這一點使用SQL或寶stgres過程語言?

編輯:我使用的PostgreSQL版本是9.4。該表由id1(整數)和id2(整數)兩列組成,它們都是主鍵。

至於如何得出結論,A是在該組第二實施例的最小(A,B,C)中,我使用這個查詢,以確定最小的ID2

SELECT id1, MIN(id2) FROM table GROUP BY id1 
+0

在第二個例子中:你如何得出結論A是集合(A,B,C)中最小的?請始終提供您的Postgres版本,最好是表格定義。 –

回答

1

假設像這樣的表:

CREATE TABLE tbl (
    id1 int 
, id2 int 
, PRIMARY KEY (id1, id2) 
); 

根據你的邏輯,循環引用是不可能的。

recursive CTE會做的工作:

WITH RECURSIVE cte AS (
    SELECT t1.id1, t1.id2, t2.id2 AS next_id2 
    FROM tbl t1 
    LEFT JOIN tbl t2 ON t2.id1 = t1.id2 

    UNION ALL 
    SELECT t1.id1, t1.next_id2, t2.id2 
    FROM cte t1 
    LEFT JOIN tbl t2 ON t2.id1 = t1.next_id2 
    WHERE t1.next_id2 IS NOT NULL -- stop iterating at end of graph 
    ) 
SELECT id1, id2 
FROM cte 
WHERE next_id2 IS NULL; -- only rows where the graph ends 

在非遞歸項,選擇行,並嘗試找到一個LEFT JOIN下一個步驟。

在遞歸術語中,用下一步替換第二個ID直到我們到達圖的末尾(next_id2 IS NULL)。

在外部SELECT只返回圖形結束的行。導致任意的排序順序。

目前還不清楚如果圖形可以分叉,你如何確定最深的兔子洞。

+0

對不起,我遲到的回覆。我使用的是PostgreSQL 9.4,表格的假設是正確的。我從來沒有使用過遞歸CTE(對數據庫來說仍然很新穎:/),所以我會研究它。謝謝:) – Aldibe

+0

p.s:是的,表中沒有循環引用。我發現的可能的問題是這兩個例子,可能是這兩個例子的結合。 – Aldibe

+0

@Aldibe:請將所有的定義信息放入問題中。按[編輯](http://stackoverflow.com/posts/36255607/edit)留下您的問題。並且請解答我最重要的澄清要求:「你如何得出結論A是最小的(A,B,C)?' –