Ознакомьтесь с этим докладом во время OpenSQLCamp, ноябрь 2009 г.
Заголовок: SQL для безумных
Также
Рекурсия с SQL
Проблема
Предположим, вы отслеживаете запасы и у вас есть поле с именем si_item, а другое - с именем si_parentid. Родитель отслеживает, к какому подклассу принадлежит элемент поставки. Например. у вас есть родительский документ, у которого есть подклассы, такие как переработанный, не переработанный. Когда кто-то берет припасы, вы хотите вернуть полное имя, например, Бумага-> Вторичное-> 20 фунтов
Решение
CREATE TABLE supplyitem(si_id integer PRIMARY KEY, si_parentid integer, si_item varchar(100));
--load up the table (multirow constructor introduced in 8.2)
INSERT INTO supplyitem(si_id,si_parentid, si_item)
VALUES (1, NULL, 'Paper'),
(2,1, 'Recycled'),
(3,2, '20 lb'),
(4,2, '40 lb'),
(5,1, 'Non-Recycled'),
(6,5, '20 lb'),
(7,5, '40 lb'),
(8,5, 'Scraps');
--Recursive query (introduced in 8.4 returns fully qualified name)
WITH RECURSIVE supplytree AS
(SELECT si_id, si_item, si_parentid, CAST(si_item As varchar(1000)) As si_item_fullname
FROM supplyitem
WHERE si_parentid IS NULL
UNION ALL
SELECT si.si_id,si.si_item,
si.si_parentid,
CAST(sp.si_item_fullname || '->' || si.si_item As varchar(1000)) As si_item_fullname
FROM supplyitem As si
INNER JOIN supplytree AS sp
ON (si.si_parentid = sp.si_id)
)
SELECT si_id, si_item_fullname
FROM supplytree
ORDER BY si_item_fullname;
Результат выглядит как
si_id | si_item_fullname
------+-----------------------------
1 | Paper
5 | Paper->Non-Recycled
6 | Paper->Non-Recycled->20 lb
7 | Paper->Non-Recycled->40 lb
8 | Paper->Non-Recycled->Scraps
2 | Paper->Recycled
3 | Paper->Recycled->20 lb
4 | Paper->Recycled->40 lb