我有一个表(在PostgreSQL数据库中),其中某些id的多行有一些值,而有些则为null。 该表看起来像这样(玩具示例):
PSQL:test/me@[local]=> SELECT * FROM t1;
id | x | y | z
----+-----+-----+----
1 | | 200 |
1 | 100 | | 42
2 | 45 | |
(3 rows)
最重要的是:我可以保证同一个字段的行没有非NULL值的行没有行。 在上面的示例中,id 1将不会有任何其他行。
我希望聚合每个id的所有值,压缩非null值。也就是说,将它转换成类似这样的东西
id | x | y | z
----+-----+-----+----
1 | 100 | 200 | 42
2 | 45 | |
(2 rows)
我最接近的是使用级联COALESCE(field1, '') || COALESCE(field2, '') || ...
,但结果不是我想要的:
PSQL:test/me@[local]=> SELECT id, COALESCE(x::TEXT || ',' , '') || COALESCE(y::TEXT || ',', '') || COALESCE(z::TEXT || ',', '') AS agg FROM t1 GROUP BY id, agg;
id | agg
----+---------
1 | 100,42,
1 | 200,
2 | 45,
(3 rows)
知道如何解决这个问题吗?
答案 0 :(得分:3)
只需使用聚合,例如min()
- 它将忽略空值:
select id,
min(x) as x,
min(y) as y,
min(z) as z
from t1
group by id;
这取决于你声称“我可以保证同一个字段中没有行,其中同一个字段具有非NULL值” - 否则这当然会返回错误的信息
或者,您可以使用array_agg()
将所有值放入数组中,以防每个ID获得多个值。但string_agg()
不会忽略空值,因此您需要为其应用过滤器:
select id,
array_agg(x) filter (where x is not null),
array_agg(y) filter (where y is not null),
array_agg(z) filter (where z is not null)
from t1
group by id;