提问人:Fabrício Matté 提问时间:4/15/2013 最后编辑:CommunityFabrício Matté 更新时间:7/12/2016 访问量:7155
将查询中的单个列聚合为多个列
Aggregate a single column in query with many columns
问:
当我在查询中有许多其他列时,是否有适当的方法来聚合单个列?
我已经尝试了这个有效的答案,但我的查询变得更加冗长。
我当前的查询如下所示:
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
查询有更多的字段和 s,重要的部分是所有这些字段都具有 1 到 1 或 1 到 0 的关系,除了我想聚合的 1 到 n 的字段,在上面的伪查询中表示。LEFT JOIN
t3.aggregated_field
由于我使用的是聚合函数,因此 和 中列出的所有字段都必须是聚合的或子句的一部分。这使我的查询方式比现在更冗长。SELECT
ORDER BY
GROUP BY
也就是说,假设是主键,当这个字段重复时,除此字段外的所有其他字段也相等。我希望这些重复的行作为具有聚合字段值的单行结果。(基本上是带有聚合列的)foo1
aggregated_field
select distinct
有没有更好的方法可以做到这一点(而不必将所有其他字段放在 中),或者我应该在后端遍历结果集,为获取此 1 到 n 关系的每一行执行查询?GROUP BY
服务器运行的是 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 位
答:
如果主要问题是计算字段 (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...
评论
foo7
foo8
SELECT
ORDER BY
=]
简单查询
使用 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
评论
DISTINCT
=]
WHERE
EXPLAIN ANALYZE
评论
string_agg
=]