Хорошо, лучшее, что я могу придумать на данный момент, - это сначала создать максимальные группы связанных идентификаторов, а затем присоединиться к таблице потенциальных клиентов, чтобы получить оставшиеся данные (см. SQL Fiddle * 1002.* для настройки, полных запросов и результатов).
Чтобы получить максимальные группы, вы можете использовать рекурсивное выражение общей таблицы, чтобы сначала увеличить группы, а затем запрос, чтобы отфильтровать результаты CTE до максимального значения.groups:
with recursive cte(grp) as (
select case when l.connected_lead_id is null then array[l.id]
else array[l.id, l.connected_lead_id]
end from leads l
union all
select grp || l.id
from leads l
join cte
on l.connected_lead_id = any(grp)
and not l.id = any(grp)
)
select * from cte c1
Выше CTE выводит несколько похожих групп, а также промежуточные группы.Предикат запроса ниже сокращает немаксимальные группы и ограничивает результаты только одной перестановкой каждой возможной группы:
where not exists (select 1 from cte c2
where c1.grp && c2.grp
and ((not c1.grp @> c2.grp)
or (c2.grp < c1.grp
and c1.grp @> c2.grp
and c1.grp <@ c2.grp)));
Результаты :
| grp |
|------------|
| 2,8 |
| 4,7 |
| 14 |
| 11,336,142 |
| 12,13 |
Затем присоедините последний запрос, приведенный выше, к своей таблице потенциальных клиентов и используйте оконные функции для получения значений оставшихся столбцов, а также отдельный оператор для сокращения его до конечного набора результатов:
with recursive cte(grp) as (
...
)
select distinct
first_value(l.id) over (partition by grp order by l.created_at) id
, first_value(l.created_at) over (partition by grp order by l.created_at) create_at
, first_value(l.on_boarded_date) over (partition by grp order by l.created_at) on_boarded_date
, first_value(l.source) over (partition by grp
order by case when l.source is null then 2 else 1 end
, l.created_at) source
, grp CONNECTED_IDS
from cte c1
join leads l
on l.id = any(grp)
where not exists (select 1 from cte c2
where c1.grp && c2.grp
and ((not c1.grp @> c2.grp)
or (c2.grp < c1.grp
and c1.grp @> c2.grp
and c1.grp <@ c2.grp)));
Результаты :
| id | create_at | on_boarded_date | source | connected_ids |
|----|----------------------|-----------------|----------|---------------|
| 2 | 2015-09-24T23:00:00Z | (null) | referral | 2,8 |
| 4 | 2015-09-25T23:00:00Z | (null) | event | 4,7 |
| 11 | 2015-09-26T23:00:00Z | 2017-07-01 | online | 11,336,142 |
| 12 | 2015-09-26T23:00:00Z | 2017-07-01 | event | 12,13 |
| 14 | 2015-09-26T23:00:00Z | (null) | (null) | 14 |