Написах отговор на подобен въпрос преди малко:Как да намеря всички свързани подграфи на ненасочена графа . В този въпрос използвах SQL Server. Вижте този отговор за подробно обяснение на междинните CTE. Адаптирах тази заявка към Postgres.
Може да се напише по-ефективно, като се използва функцията за масив на Postgres, вместо да се свързва пътя в текст
колона.
WITH RECURSIVECTE_IdentsAS( SELECT old AS Ident FROM identities UNION SELECT new AS Ident FROM identities),CTE_PairsAS( SELECT old AS Ident1, new AS Ident2 FROM identities WHERE old <> new UNION SELECT new AS Ident1, old AS Ident2 FROM identities WHERE old <> new),CTE_RecursiveAS( SELECT CTE_Idents.Ident AS AnchorIdent, Ident1, Ident2, ',' || Ident1 || ',' || Ident2 || ',' AS IdentPath, 1 AS Lvl FROM CTE_Pairs INNER JOIN CTE_Idents ON CTE_Idents.Ident =CTE_Pairs.Ident1 UNION ALL SELECT CTE_Recursive.AnchorIdent, CTE_Pairs.Ident1, CTE_Pairs.Ident2, CTE_Recursive.IdentPath || CTE_Pairs.Ident2 || ',' AS IdentPath, CTE_Recursive.Lvl + 1 AS CTE_Recursive.Lvl_Pal FROM AS Lvl INNER JOIN CTE_Recursive ON CTE_Recursive.Ident2 =CTE_Pairs.Ident1 WHERE CTE_Recursive.IdentPath NOT LIKE ('%,' || CTE_Pairs.Ident2 || ',%')),CTE_Recursi onResultas (Изберете Anchorident, Ident1, Ident2 от CTE_RECURSIVE), CTE_CLEANRESULTAS (Изберете Anchordent, Ident1 като идентификация от CTE_RECURSIONRESULT UNION SELECT ANCHOREDID, IDECTS като идентификация от cte_recursionresult), cte_groupsas (select cte_idents. Ident) ORDER BY COALESCE(CTE_CleanResult.Ident, CTE_Idents.Ident)) AS AllIdents FROM CTE_Idents LEFT JOIN CTE_CleanResult ON CTE_CleanResult.AnchorIdent =CTE_Idents.Ident GROUP BY CTE_Idents.Ident)SELECT AllIdentsFROM CTE_GroupsGROUP BY All Idents; BY AllIdents
Добавих един ред (7,X,Y)
към вашите примерни данни.
Резултат
<предварителен код>| алиденти ||--------------------|| Лидия, Мери, Нанси || Албърт, Боб, Чарлз || X,Y || Зоуи |