如何使用 postgresql 按多列中表示的值进行聚合
Posted
技术标签:
【中文标题】如何使用 postgresql 按多列中表示的值进行聚合【英文标题】:How to aggregate by values represented in multiple columns with postgresql 【发布时间】:2021-03-05 18:23:07 【问题描述】:我正在使用 postgresql 8.3.23 我有一个表,其中一个 ip 表示为 3 个不同的列。 在不使用多个连接和多个查询的情况下,按 IP 聚合并按列获取总和的最佳方法是什么?
表格
source | trans | dest |
---|---|---|
ip1 | ip2 | |
ip1 | ip1 | ip3 |
ip1 | ip2 | ip3 |
ip2 | ip4 | ip5 |
我想要得到什么
ip | source | trans | dest |
---|---|---|---|
ip1 | 3 | 1 | 0 |
ip2 | 1 | 1 | 1 |
ip3 | 0 | 0 | 2 |
ip4 | 0 | 1 | 0 |
ip5 | 0 | 0 | 1 |
【问题讨论】:
为什么你使用的 Postgres 版本已经超过 7 年了? 简单来说,这是一个基于postgresql 8.3.23的Greenplum数据库。迁移到更体面的版本需要完全重建,这对于包含 3.8 PB 数据的数据库来说具有挑战性 【参考方案1】:您可以取消透视并重新聚合:
select ip, sum(source), sum(trans), sum(dest)
from ((select source as ip, 1 as source, 0 as trans, 0 as dest
from t
) union all
(select trans as ip, 0 as source, 1 as trans, 0 as dest
from t
) union all
(select dest as ip, 0 as source, 0 as trans, 1 as dest
from t
)
) t
group by ip;
肯定有不同的方式来表达这种逻辑。但是谁还记得 Postgres 8.3 支持什么?
【讨论】:
此查询包含拼写错误(第二个查询是“select trans”作为 ip 而不是“select source”等)但这绝对是我一直在寻找的技巧,谢谢。我将在下面发布完整的答案。 @ChrisChris。 . .谢谢你。固定。【参考方案2】:使用 Gordon 的技巧,我以以下查询结束。由于它用于汇总每天摄取的 55 亿个事件,其中一些 IP 过度表示,因此在子查询中获取总和结果证明效率更高。
select ip, sum(source_count) as source_count, sum(trans_count) as trans_count, sum(dest_count) as dest_count
from ((select source as ip, count(*) as source_count, 0 as trans_count, 0 as dest_count
from t where source is not null
group by 1,3,4
) union all
(select trans as ip, 0 as source_count, count(*) as trans_count, 0 as dest_count
from t where trans is not null
group by 1,2,4
) union all
(select dest as ip, 0 as source_count, 0 as trans_count, count(*) as dest_count
from t where dest is not null
group by 1,2,3
)
) t
group by ip
order by ip;
【讨论】:
以上是关于如何使用 postgresql 按多列中表示的值进行聚合的主要内容,如果未能解决你的问题,请参考以下文章