如何使用 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 按多列中表示的值进行聚合的主要内容,如果未能解决你的问题,请参考以下文章

在 python 的 berkeley db 中表达多列?

如何在postgresql中删除多列

列出引用 PostgreSQL 中表的存储函数

如何避免PostgreSQL中表的OID列?

如何在 MySQL Select 语句中按多列分组

如何将(r,球形谐波)空间中表示的数据内插到常规笛卡尔网格(F90)?