受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: devel

F.18. intagg #

intagg 模块提供一个整数聚合器和一个枚举器。 由于已经有内置函数提供了其能力的超集,所以 intagg 现已过时。 不过,该模块仍作为这些内置函数的兼容性包装器提供。

F.18.1. 函数 #

聚合器是聚合函数int_array_aggregate(integer), 它会生成一个整数数组,其中恰好包含输入给它的那些整数。 这是对array_agg的包装器,后者对任意数组类型都能做同样的事情。

枚举器是函数int_array_enum(integer[]), 它返回setof integer。本质上,它是聚合器的逆操作: 给定一个整数数组,将其展开为一组行。 这是对unnest的包装器,后者对任意数组类型都能做同样的事情。

F.18.2. 使用示例 #

许多数据库系统都有多对多表这一概念。这样的表通常位于两个带索引的表之间,例如:

CREATE TABLE left_table  (id INT PRIMARY KEY, ...);
CREATE TABLE right_table (id INT PRIMARY KEY, ...);
CREATE TABLE many_to_many(id_left  INT REFERENCES left_table,
                          id_right INT REFERENCES right_table);

它通常按如下方式使用:

SELECT right_table.*
FROM right_table JOIN many_to_many ON (right_table.id = many_to_many.id_right)
WHERE many_to_many.id_left = item;

这将返回左侧表中某个条目在右侧表中对应的所有条目。 这是 SQL 中非常常见的一种构造。

但是,如果many_to_many表中的条目非常多, 这种方法就会变得相当繁琐。通常,对于左侧表中的某个特定条目, 右侧表中的每个对应条目都要执行一次索引扫描并取回一行。 如果你的系统非常动态,那就没有太多办法。不过,如果有一部分数据相当静态, 你可以借助聚合器创建一个汇总表。

CREATE TABLE summary AS
  SELECT id_left, int_array_aggregate(id_right) AS rights
  FROM many_to_many
  GROUP BY id_left;

这样会创建一个表,其中左侧每个条目对应一行,并附带一个由右侧条目组成的数组。 不过,如果没有某种使用该数组的方法,它就几乎没有用处;这正是数组枚举器存在的原因。 你可以这样做:

SELECT id_left, int_array_enum(rights) FROM summary WHERE id_left = item;

上面这个使用int_array_enum的查询,产生的结果与下面的查询相同:

SELECT id_left, id_right FROM many_to_many WHERE id_left = item;

区别在于,针对汇总表的查询只需要从表中取出一行, 而直接查询many_to_many则必须对每个条目都进行索引扫描并取回一行。

在某个系统上,EXPLAIN显示,某个查询的代价从 8488 降到了 329。 原始查询是一个涉及many_to_many表的连接,后来被替换为:

SELECT id_right, count(id_right) FROM
  ( SELECT id_left, int_array_enum(rights) AS id_right
    FROM summary
    JOIN (SELECT id FROM left_table
          WHERE id = item) AS lefts
    ON (summary.id_left = lefts.id)
  ) AS list
  GROUP BY id_right
  ORDER BY count DESC;

提交更正

如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。