4

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

我已经尝试过这个有效的答案,但我的查询变得更加冗长。

我当前的查询如下所示:

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 JOINs,重要的部分是所有这些字段都具有 1 到 1 或 1 到 0 的关系,除了我要聚合的 1 到 n 的一个字段,t3.aggregated_field在上面的伪查询中表示。

由于我使用的是聚合函数,SELECTand中列出的所有字段都ORDER 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 位

4

2 回答 2

5

简单查询

使用 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 中提供了一个测试用例来证明这个相关答案中的观点:

由于您指的是这个相关的答案:不,DISTINCT在这种情况下根本没有帮助。

于 2013-04-15T19:32:47.483 回答
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...字段按照它们在选择列表中出现的顺序排列。

于 2013-04-15T15:08:23.803 回答