Ich habe eine Tabelle identities
(d. H. Aliase) für eine beliebige Anzahl von Personen. Jede Zeile hat einen vorherigen Namen und einen neuen Namen. In der Produktion gibt es etwa 1 M Reihen. Zum Beispiel:Suchen der Spanning-Gesamtstruktur (MIT RECURSIVE, PostgreSQL 9.5)
id, old, new
---
1, 'Albert', 'Bob'
2, 'Bob', 'Charles'
3, 'Mary', 'Nancy'
4, 'Charles', 'Albert'
5, 'Lydia', 'Nancy'
6, 'Zoe', 'Zoe'
Was ich will ist die Liste der users
und verweisen alle ihre jeweiligen Identitäten zu generieren. Dies ist analog zu allen Knoten in jeder graphischen Darstellung der verbundenen Identitäten zu finden, oder der Suche nach den Spanning Wald:
User 1: Albert, Bob, Charles (identities: 1,2,4)
User 2: Mary, Nancy, Lydia (identities: 3,5)
User 3: Zoe (identities: 6)
Ich habe mit PostgreSQL bastelt WITH RECURSIVE
, aber es ergibt sich beide Sätze und Teilsätze für jeden. Zum Beispiel:
1,2,4 <-- spanning tree: good
2 <-- subset: discard
3,5 <-- spanning tree: good
4 <-- subset: discard
5 <-- subset: discard
6 <-- spanning tree: good
Was muß ich tun, um nur die vollständigen Sätze von Identitäten zu erzeugen (das heißt der Spanning-Tree) für jeden Benutzer?
SQLFiddle: http://sqlfiddle.com/#!15/9eaed/4 mit meinem neuesten Versuch. Hier ist der Code:
WITH RECURSIVE search_graph AS (
SELECT id
, id AS min_id
, ARRAY[id] AS path
, ARRAY[old,new] AS emails
FROM identities
UNION
SELECT identities.id
, LEAST(identities.id, sg.min_id)
, (sg.path || identities.id)
, (sg.emails || identities.old || identities.new)
FROM search_graph sg
JOIN identities ON (identities.old = ANY(sg.emails) OR identities.new = ANY(sg.emails))
WHERE identities.id <> ALL(sg.path)
)
SELECT array_agg(DISTINCT(p)) from search_graph, unnest(path) p GROUP BY min_id;
Und die Ergebnisse:
1,2,4
2
3,5
4
5
6
Ich habe das Gefühl, dass die Teilmengen in den Ergebnissen auftauchen werden, weil sie keine Duplikate von anderen Zwischenergebnissen exakt und damit sind sie nicht eliminiert. Dies geschieht, weil ich redundante Information in 'search_graph' speichere und keine Dinge wie den Inhalt von' path' sortiere. –
'distinct' ist *** nicht *** eine Funktion. –