如何在PostgreSQL中将分组频次统计结果合并回原表?
解决PostgreSQL中UPDATE分组统计值到原表的报错问题
你遇到的报错more than one row returned by a subquery used as an expression,是因为SET子句里的子查询没有和主表的行做关联,直接返回了视图里的所有3行数据,而UPDATE操作每一行只能接收单个值,因此产生冲突。
以下是几种可行的解决方案:
方案1:关联子查询更新(基于已有的视图)
直接在子查询中添加关联条件,让它仅返回当前行对应Group的GroupSize:
UPDATE "Titanic" SET "GroupSize" = ( SELECT "GroupSize" FROM "GroupSize" WHERE "GroupSize"."Group" = "Titanic"."Group" );
该语句会遍历Titanic表的每一行,通过Group字段匹配视图中的对应记录,将正确的分组大小赋值给GroupSize列。
方案2:使用UPDATE FROM语法(PostgreSQL专属,更直观)
PostgreSQL支持通过FROM子句关联更新源,写法更清晰:
UPDATE "Titanic" t SET "GroupSize" = gs."GroupSize" FROM "GroupSize" gs WHERE t."Group" = gs."Group";
这里给表和视图分别起别名t和gs,通过Group字段关联后批量更新所有匹配行。
方案3:无需视图,直接在UPDATE中计算分组大小
如果不需要保留统计视图,可以直接在UPDATE语句内完成分组计数,一步到位:
UPDATE "Titanic" t SET "GroupSize" = ( SELECT COUNT(*) FROM "Titanic" WHERE "Group" = t."Group" );
这个子查询会针对每一行的Group值,统计整个表中该Group的总记录数,直接赋值给当前行的GroupSize。
若数据量较大,也可以用窗口函数实现高效计算:
UPDATE "Titanic" SET "GroupSize" = sub."GroupSize" FROM ( SELECT "PassengerId", COUNT(*) OVER (PARTITION BY "Group") AS "GroupSize" FROM "Titanic" ) sub WHERE "Titanic"."PassengerId" = sub."PassengerId";
窗口函数COUNT(*) OVER (PARTITION BY "Group")会一次性计算所有分组的大小,再通过PassengerId关联更新原表。
内容的提问来源于stack exchange,提问作者Andy McDill
相关产品推荐
相关产品推荐

