私は任意の人数のテーブルidentities
(エイリアス)を持っています。各行には以前の名前と新しい名前があります。プロダクションでは、約1M行あります。たとえば:スパニングツリー(WITH 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'
は、私が欲しいのはusers
のリストを生成し、それぞれのアイデンティティのすべてを参照することです。
User 1: Albert, Bob, Charles (identities: 1,2,4)
User 2: Mary, Nancy, Lydia (identities: 3,5)
User 3: Zoe (identities: 6)
私はPostgreSQLのWITH RECURSIVE
いじりてきたが、それはそれぞれのセットとサブセットの両方が得られます。これは、接続されているアイデンティティの各グラフ内のすべてのノードを見つけ、またはスパニング森を見つけることに似ています。たとえば、次のように
1,2,4 <-- spanning tree: good
2 <-- subset: discard
3,5 <-- spanning tree: good
4 <-- subset: discard
5 <-- subset: discard
6 <-- spanning tree: good
私は、ユーザーごとにアイデンティティのフルセット(すなわち、スパニングツリー)を生成するために行うには何が必要ですか?
SQLFiddle:http://sqlfiddle.com/#!15/9eaed/4私の最新の試み。ここでは、コードです:
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;
と結果:
1,2,4
2
3,5
4
5
6
私は、彼らがそれ故に、他の中間結果の重複を強要していないため、サブセットが結果に表示されているという感覚を持って、彼らはありませんよ削除されました。これは、 'search_graph'に冗長な情報を保存していて、' path'の内容のようなものをソートしていないために発生します。 –
'distinct'は***関数ではありません***。 –