在查询中聚合具有许多列的单个列

时间:2013-04-15 14:48:36

标签: sql postgresql aggregate-functions

当我在查询中有许多其他列时,是否有合适的方法来聚合单个列?

我尝试了this answer,但我的查询变得更加冗长。

我当前的查询如下所示:

SELECT t1.foo1, t1.foo2, t2.foo3, t2.foo4, string_agg(t3.aggregated_field, ', ')
FROM tbl1 t1
LEFT JOIN tbl2 t2 ON t1.id = t2.fkeyid
LEFT JOIN tbl3 t3 ON t2.id = t3.fkeyid
GROUP BY t1.foo1, t1.foo2, t2.foo3, t2.foo4, t2.foo5, t2.foo6
ORDER BY t2.foo5, t2.foo6

查询还有更多字段和LEFT JOIN s,重要的是所有这些字段都有1比1或1比0的关系,除了一个我希望聚合的1到n的字段,由上面的伪查询中的t3.aggregated_field

由于我正在使用聚合函数,因此SELECTORDER BY中列出的所有字段必须是聚合的,或者是GROUP BY子句的一部分。这使我的查询方式比现在更冗长。

即,假设foo1是主键,当重复此字段时,除aggregated_field之外的所有其他字段也相等。我希望这些重复的行作为单行结果与聚合字段值。 (基本上是带有聚合列的select distinct

有没有更好的方法来执行此操作(无需将所有其他字段放在GROUP BY中),或者我是否应该迭代后端的结果集,为获取此1的每一行执行查询与n的关系?


服务器正在运行PostgreSQL 9.1.9,更具体地说:

  

x86_64-unknown-linux-gnu上的PostgreSQL 9.1.9,由gcc(GCC)4.1.2 20080704(Red Hat 4.1.2-54)编译,64位

2 个答案:

答案 0 :(得分:4)

简单查询

对于PostgreSQL 9.1或更高版本,这可以更简单。正如这个密切相关的答案所解释的那样:

GROUP BY表的主键就足够了。时间:

  

foo1是主键

..您可以将示例简化为:

SELECT foo1, foo2, foo3, foo4, foo5, foo6, string_agg(aggregated_field, ', ')
FROM   tbl1
GROUP  BY 1
ORDER  BY foo7, foo8;  -- have to be spelled out, since not in select list!

使用多个表进行查询

但是,因为你有:

  

更多字段和LEFT JOIN,重要的是所有这些字段都有1比1或1比0的关系,除了一个我希望聚合的1到n的字段

.. 首先聚合,稍后加入

应该更快更简单
SELECT t1.foo1, t1.foo2, ...
     , t2.bar1, t2.bar2, ...
     , a.aggregated_col 
FROM   tbl1 t1
LEFT   JOIN tbl2 t2 ON ...
...
LEFT   JOIN (
   SELECT some_id, string_agg(agg_col, ', ') AS aggregated_col
   FROM   agg_tbl a ON ...
   GROUP  BY some_id
   ) a ON a.some_id = ?.some_id
ORDER  BY ...

这样,查询的大部分根本不需要聚合。

我最近在SQL Fiddle中提供了一个测试用例来证明这个相关答案的重点:

由于您指的是this related answer:不,DISTINCT在这种情况下根本无法提供帮助。

答案 1 :(得分:1)

如果主要问题是计算字段(foox),那么这可以帮助:

SELECT foo1, foo2, foo3, foo4, foo5, foo6, string_agg(aggregated_field, ', ')
FROM tbl1
GROUP BY 1, 2, 3, 4, 5, 6
ORDER BY 5, 6

1, 2...是按照它们在选择列表中显示的顺序排列的字段。