2012-04-05 63 views
6

我有表,樹結構中的數據,列idcategoryparent_idPostgreSQL的複製樹表

現在我需要複製一個節點及其孩子到另一個節點,而拷貝,類別必須是相同的,但新的ID和PARENT_ID ..

我的投入將是node to copy & destination node to copy

我已經解釋了圖像文件中的樹形結構..

我需要一個函數來做到這一點..,

的PostgreSQL 9.1.2版本

Column | Type |     Modifiers      
-----------+---------+------------------------------------------------- 
id  | integer | not null default nextval('t1_id_seq'::regclass) 
category | text | 
parent_id | integer | 
Indexes: 
    "t1_pkey" PRIMARY KEY, btree (id) 
Foreign-key constraints: 
    "fk_t1_1" FOREIGN KEY (parent_id) REFERENCES t1(id) 
Referenced by: 
    TABLE "t1" CONSTRAINT "fk_t1_1" FOREIGN KEY (parent_id) REFERENCES t1(id) 
+0

幫助我獲得2個輸入和做這項工作的功能... – MAHI 2012-04-05 08:33:25

+0

所以基本上你想克隆一個子樹?硬。我正在考慮。 – wildplasser 2012-04-05 10:00:56

+0

是它的硬..我試​​過了很多功能..沒有用.. – MAHI 2012-04-05 10:04:08

回答

5

(下測試PostgreSQL 8.4.3)

以下查詢爲節點4下的子樹(請參閱nextval)分配新ID,然後找到相應的積累父母的新ID (請參閱LEFT JOIN)。

WITH RECURSIVE CTE AS (
    SELECT *, nextval('t1_id_seq') new_id FROM t1 WHERE id = 4 
    UNION ALL 
    SELECT t1.*, nextval('t1_id_seq') new_id FROM CTE JOIN t1 ON CTE.id = t1.parent_id 
) 
SELECT C1.new_id, C1.category, C2.new_id new_parent_id 
FROM CTE C1 LEFT JOIN CTE C2 ON C1.parent_id = C2.id 

結果(在你的測試數據):

new_id category new_parent_id 
------ -------- ------------- 
9  C4   
10  C5   9 
11  C6   9 
12  C7   10 

一旦你的,它很容易將它裝回表,你就必須要小心重新連接的子樹的根用合適的親本(在這種情況下如圖8所示,參見COALESCE(new_parent_id, 8)):

INSERT INTO t1 
SELECT new_id, category, COALESCE(new_parent_id, 8) FROM (
    WITH RECURSIVE CTE AS (
     SELECT *, nextval('t1_id_seq') new_id FROM t1 WHERE id = 4 
     UNION ALL 
     SELECT t1.*, nextval('t1_id_seq') new_id FROM CTE JOIN t1 ON CTE.id = t1.parent_id 
    ) 
    SELECT C1.new_id, C1.category, C2.new_id new_parent_id 
    FROM CTE C1 LEFT JOIN CTE C2 ON C1.parent_id = C2.id 
) Q1 

在那之後,該表包含以下數據:

new_id category new_parent_id 
------ -------- ------------- 
1  C1 
2  C2   1 
3  C3   1 
4  C4   2 
5  C5   4 
6  C6   4 
7  C7   5 
8  C8   3 
9  C4   8 
10  C5   9 
11  C6   9 
12  C7   10 
+0

這太棒了。我沒有想到遞歸+下一個組合可以做到這一點,而不需要額外的狀態變量。起首! – wildplasser 2012-04-05 16:33:12

+0

@Branko謝謝,它在9.1.2中工作得很好。 – MAHI 2012-04-06 04:32:31

+0

任何人都可以幫助我[this](http://stackoverflow.com/questions/9077266/postgresql-update-tree-table-with-rows -from-相同表逐個改變-ID-andparen) – MAHI 2012-04-06 05:00:41