2016-12-27 72 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的性能。

另一種方法是使用兩個聚合:

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; 

但是,你的版本intersect可能會更快。

+0

非常感謝。第一個將查詢時間從1分鐘縮短到〜35秒。 –

1

最快的方法通常是使用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替換爲表格的名稱。

相關問題