2017-07-25 3 views
0

私はリレーショナルテーブル(一対多)を持っており、関連アイテムを与えるID間の類似性を効率的に取得する必要があります。テーブルのようなその何か:私は必要なものは、1対多テーブルの列を数えることに基づいて最も近いIDを効率的に取得します。

id item 
1 A2231 
1 A2134 
2 A2134 
2 B2313 
... 

は、すべてのIDの間で共通している行数を取得することです:

a_id b_id count_items 
1  2  1 
1  3  0 
2  1  1 
... 

私は、クエリを作ったが、そのO(N2)しています、スプール空間のために動作しません。

SELECT A.ID AS a_id, B.ID AS b_id, COUNT(B.item) AS count_items 
FROM Tab AS A LEFT JOIN Tab AS B --same table 
ON (A.item = B.item) 
GROUP BY A.ID, B.ID 

EDIT:そこIt'a

n_rows ~ 50MM 
n_items ~ 100K 
n_ids ~ 170K 
combinations id/item are unique 

効率的にこれを達成する方法はありますか? ありがとうございます!

+0

いくつかの統計情報を共有できますか:行数、項目数、項目あたりの行数は最大ですか? IDとアイテムの組み合わせは一意ですか? – dnoeth

+0

@dnoeth edited;) –

+0

ベストアイテム解決:PIの 'item'でPIをスプールしている場合は、より小さなサブセットに対して実行することができます。 1バッチあたり10,000個のアイテム。 Btwの場合は、おそらく別の条件 '(A.ID <> B.ID)'を追加する必要があります。そうでなければ、ゼロカウントを得ることはありません(外部結合は必要ありません)。 – dnoeth

答えて

0

私が参加ちょうどインナーを使用して起動します:

SELECT A.ID, B.ID, COUNT(*) AS count_items 
FROM Tab A LEFT JOIN 
    Tab B --same table 
    ON A.item = B.item 
GROUP BY A.ID, B.ID; 

次のあなたのテーブルには、重複している場合、これはうまくいくかもしれない:

with t as (
     select distinct id, item 
     from tab 
    ) 
select a.id, b.id, count(*) 
from t a join 
    t b 
    on a.item = b.item 
group by a.id, b.id; 

そして最後に、あなたはすべてのペアをしたい場合項目:次に、

with t as (
     select distinct id, item 
     from tab 
    ) 
select i1.id, i2.id, count(b.id) 
from (select distinct id from tab) i1 cross join 
    (select distinct id from tab) i2 left join 
    t a 
    on t.id = i1.id left join 
    t b 
    on b.id = i2.id and a.item = b.item 
group by i1.id, i2.id; 
+0

まだスペースに問題がありますが、o(n2)の組み合わせに入らない方法がありますか? –

関連する問題