Учитывая эту таблицу идентификаторов:
╔═══════╤═══════╗
║ tid_1 │ tid_2 ║
╠═══════╪═══════╣
║ 1 │ 2 ║
║ 1 │ 9 ║
║ 1 │ 10 ║
║ 2 │ 9 ║
║ 2 │ 10 ║
║ 3 │ 4 ║
║ 9 │ 10 ║
║ 9 │ 12 ║
║ 9 │ 14 ║
║ 12 │ 14 ║
╚═══════╧═══════╝
и при условии, что в каждой строке есть метки наборов, которые считаются эквивалентными, как я могу (в PostgreSQL) найти транзитивный набор эквивалентностей?
Другими словами, я знаю, что вещи в коробке 14 можно выбросить вместе с
вещи в коробке 12; вещи в коробке 12 с вещами в коробке 9; и коробка 9,
в свою очередь ничем не отличается от вещей в коробках 2 и 1.
Затем я хочу пойти и назначить новый идентификатор набора (например, используя наименьший идентификатор из
переходная группа) так что я получаю
╔═══════╤═══════╗
║ tid │ sid ║
╠═══════╪═══════╣
║ 1 │ 1 ║
║ 2 │ 1 ║
║ 3 │ 3 ║
║ 4 │ 3 ║
║ 9 │ 1 ║
║ 10 │ 1 ║
║ 12 │ 1 ║
║ 14 │ 1 ║
╚═══════╧═══════╝
Мне удалось подойти к этому моменту, который, как я полагаю, является частью решения:
create view transitive_closure as (
with recursive containment as ( select
p1.tid_1 as tid_1,
p1.tid_2 as tid_2,
array[ p1.tid_1 ] as chain,
false as is_cyclic
from links as p1
union all
select distinct
p2.tid_1 as tid_1,
p2.tid_2 as tid_2,
tc.chain || p2.tid_1 as chain,
p2.tid_2 = any( chain ) as is_cyclic
from links as p2
join containment as tc on ( p2.tid_1 = tc.tid_2 )
)
select distinct tid_1, tid_3 as tid_2 from containment );