2012-04-05 6 views
6

У меня есть таблица с древовидной структурой, столбцы id, category, parent_idPostgresql копирования данных в таблице дерева

Теперь мне нужно скопировать узел и его ребенка к другому узлу, при копировании категория должна быть такой же, но с новым идентификатором и 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

+0

Итак, в основном вы хотите клонировать поддерево? Жесткий. Я думаю об этом. – wildplasser

+0

Да, его трудно .. Я пробовал с множеством функций .. Не использовать .. – MAHI

ответ

5

(протестировано под PostgreSQL 8.4.3)

Следующий запрос присваивает новые идентификаторы поддереву под узлом 4 (см. nextval), а затем находит соответствие с новыми идентификаторами родителей (см. 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

+0

@Branko спасибо, он тоже работал в 9.1.2 .... – MAHI

+0

может кто-нибудь помочь мне с [этим] (http://stackoverflow.com/questions/9077266/postgresql-update-tree-table-with-rows -из-же-таблица с меняющимся-ID-andparen) – MAHI

Смежные вопросы