PostgreSQL - 检查反向值行是不是存在的最佳方法
Posted
技术标签:
【中文标题】PostgreSQL - 检查反向值行是不是存在的最佳方法【英文标题】:PostgreSQL - Best way to check the existance of reverse valued rowsPostgreSQL - 检查反向值行是否存在的最佳方法 【发布时间】:2016-12-27 13:18:42 【问题描述】:我知道我找不到合适的标题。
为了论证,我有这张表:
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
的版本可能会更快。
【讨论】:
非常感谢。第一个将我的查询时间从 1 分钟缩短到约 35 秒。【参考方案2】:最快的方法通常是使用join
(特别是如果您在两列上有索引):
select count(*)/2
from sr as t1 join sr as t2 on t2.sender=t1.receiver and t2.receiver=t1.sender;
如果您没有带有 sender=receiver 的行,您也可以使用:
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 替换为您的表名。
【讨论】:
以上是关于PostgreSQL - 检查反向值行是不是存在的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章