2016-12-27 8 views
3

私は適切なタイトルを見つけることができませんでした。PostgreSQL - 逆の行の存在を確認する最善の方法

議論のため、私はこのテーブルを持っている:

sender|receiver 
    a | b 
    c | d 
    d | e 
    b | a 
    f | q 
    q | f 
    t | u 

は、私はテーブルの上に逆を持っている行数を計算します。たとえば、行a | bは、表上でb | aと逆になります。同様に、f | qはテーブル上でq | fと逆になります。だから、このテーブルでは、答えとして「2」が必要です。

私はこれを計算する:

CREATE TABLE #temptab 
(
    sender  VARCHAR, 
    receiver VARCHAR 
); 

CREATE TABLE #temptab2 
(
    receiver VARCHAR, 
    sender  VARCHAR 
); 

INSERT INTO #temptab 
(
    sender, 
    receiver 
) 
SELECT DISTINCT sender, 
     receiver 
FROM table 

INSERT INTO #temptab2 
(
    receiver, 
    sender 
) 
SELECT DISTINCT receiver, 
     sender 
FROM table 

SELECT COUNT(sender) 
FROM (SELECT sender,receiver FROM #temptab INTERSECT SELECT receiver,sender FROM #temptab2 

私は速くこれを行うことができます方法はありますか?

答えて

1

私だけだろう:

select count(*) 
from #temptab t 
where t.sender < t.receiver and 
     exists (select 1 
       from #temptab tt 
       where tt.sender = t.receiver and tt.receiver = t.sender 
      ); 

これはPostgresの上で非常にうまく動作するはずです。 Amazon Redshiftのパフォーマンスについてはわかりません。しかし、intersectとバージョンが速いかもしれない

select count(*) 
from (select least(sender, receiver) as x1, greatest(sender_receiver) as x2, 
      count(distinct sender) as cnt 
     from #temptab 
     group by x1, x2 
    ) t 
where cnt = 2; 

もう一つの方法は、二つの集計を使用します。

+0

ありがとうございました。最初のものはクエリ時間を1分から35秒に短縮しました。 –

1

通常(あなたが2列に索引を持っている場合は特に)joinを使用している最速の方法:

select count(*)/2 
from sr as t1 join sr as t2 on t2.sender=t1.receiver and t2.receiver=t1.sender; 

あなたはまた、使用することができ、送信者=受信側で何の行を持っていない場合:

select count(*) 
from sr as t1 join sr as t2 on t2.sender=t1.receiver and t2.receiver=t1.sender 
where t1.sender < t1.receiver; 

どちらの場合も、srはテーブル名で置き換えてください。

関連する問題