Транзитивное замыкание в SQL
Последнее время мне часто приходится заниматься обработкой данных, для этого я, в основном, использую замечательную БД PostgreSQL. Хочу поделиться решением одной из проблем, c которой мне недавно пришлось столкнуться — нахождение транзитивного замыкания некоторого отношения.
Допустим у нас есть следующая табличка
postgres=# table rel;
a | b
---+---
1 | 2
2 | 3
(2 rows)
и мы хотим получить её транзитивное замыкание, то есть добавить строчку (1, 3). Для этого в SQL2003 существует recursive common table expressions, вот как это можно сделать с их помощью:
postgres=# with recursive c as (
select * from rel
union
select rel.a, c.b from rel join c on rel.b = c.a) table c;
a | b
---+---
1 | 2
2 | 3
1 | 3
(3 rows)
просто и со вкусом!