🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# F.17\. intagg `intagg`模块提供一个整数聚合器和一个枚举器。`intagg` 现在已经废弃了,因为内置的函数提供它的能力的一个超集。不过, 该模块仍然作为内置函数的兼容性封装器提供。 ## F.17.1\. 函数 聚合器是一个生产正好包含输入的整数的整数数组的聚合函数`int_array_aggregate(integer)`。 这是`array_agg`的封装器,`array_agg`对于任意数组类型做相同的事情。 枚举器是返回`setof integer`类型的函数`int_array_enum(integer[])`。 本质上是聚合器的反向操作:给出一个整数数组,将其展开为一组行。 这是`unnest`的封装器,`unnest`对于任意数组类型做相同的事情。 ## F.17.2\. 示例使用 许多数据库系统有一到多个表的概念。这样的一个表通常位于两个索引表之间,例如: ``` CREATE TABLE left (id INT PRIMARY KEY, ...); CREATE TABLE right (id INT PRIMARY KEY, ...); CREATE TABLE one_to_many(left INT REFERENCES left, right INT REFERENCES right); ``` 通常这样使用: ``` SELECT right.* from right JOIN one_to_many ON (right.id = one_to_many.right) WHERE one_to_many.left = _item_; ``` 这将返回所有在左手边的表里有记录的右手边表里的条目。这在SQL中是一个非常普通的构造。 现在,这个方法在一个有非常大数量的记录的`one_to_many`表里是很难处理的。 通常,像这样的连接将会导致索引扫描和抓取表中有左手边记录的每个右手边记录。 如果你有一个非常动态的系统,那么没有什么你可以做的。不过,如果你有一些静态的数据, 你可以使用该聚合器创建一个汇总表。 ``` CREATE TABLE summary AS SELECT left, int_array_aggregate(right) AS right FROM one_to_many GROUP BY left; ``` 这将创建一个表,这个表有每个左边的条目和一个左边条目的数组。 现在,如果没有使用该数组的方法则是相当无用的;这就是为什么有一个数组枚举器。 你可以 ``` SELECT left, int_array_enum(right) FROM summary WHERE left = _item_; ``` 上面的查询使用`int_array_enum`产生下面相同的结果 ``` SELECT left, right FROM one_to_many WHERE left = _item_; ``` 不同之处是针对summary表的查询必须只从表中获取一行,而针对`one_to_many` 的直接查询必须索引扫描然后从每条记录中获取一行。 在一个系统上,一个显示了消耗8488的查询的`EXPLAIN`减少到消耗329。 原始查询时一个包括`one_to_many`表的连接,替换为: ``` SELECT right, count(right) FROM ( SELECT left, int_array_enum(right) AS right FROM summary JOIN (SELECT left FROM left_table WHERE left = _item_) AS lefts ON (summary.left = lefts.left) ) AS list GROUP BY right ORDER BY count DESC; ```