1 <!-- $PostgreSQL: pgsql/doc/src/sgml/intagg.sgml,v 1.3 2007/12/10 05:32:51 tgl Exp $ -->
6 <indexterm zone="intagg">
7 <primary>intagg</primary>
11 The <filename>intagg</filename> module provides an integer aggregator and an
16 <title>Functions</title>
19 The aggregator is an aggregate function
20 <function>int_array_aggregate(integer)</>
21 that produces an integer array
22 containing exactly the integers it is fed.
23 Here is a not-tremendously-useful example:
27 test=# select int_array_aggregate(i) from
28 test-# generate_series(1,10,2) i;
36 The enumerator is a function
37 <function>int_array_enum(integer[])</>
38 that returns <type>setof integer</>. It is essentially the reverse
39 operation of the aggregator: given an array of integers, expand it
40 into a set of rows. For example,
44 test=# select * from int_array_enum(array[1,3,5,7,9]);
58 <title>Sample Uses</title>
61 Many database systems have the notion of a one to many table. Such a table
62 usually sits between two indexed tables, for example:
66 CREATE TABLE left (id INT PRIMARY KEY, ...);
67 CREATE TABLE right (id INT PRIMARY KEY, ...);
68 CREATE TABLE one_to_many(left INT REFERENCES left, right INT REFERENCES right);
72 It is typically used like this:
76 SELECT right.* from right JOIN one_to_many ON (right.id = one_to_many.right)
77 WHERE one_to_many.left = <replaceable>item</>;
81 This will return all the items in the right hand table for an entry
82 in the left hand table. This is a very common construct in SQL.
86 Now, this methodology can be cumbersome with a very large number of
87 entries in the <structname>one_to_many</> table. Often,
88 a join like this would result in an index scan
89 and a fetch for each right hand entry in the table for a particular
90 left hand entry. If you have a very dynamic system, there is not much you
91 can do. However, if you have some data which is fairly static, you can
92 create a summary table with the aggregator.
96 CREATE TABLE summary as
97 SELECT left, int_array_aggregate(right) AS right
103 This will create a table with one row per left item, and an array
104 of right items. Now this is pretty useless without some way of using
105 the array; that's why there is an array enumerator. You can do
109 SELECT left, int_array_enum(right) FROM summary WHERE left = <replaceable>item</>;
113 The above query using <function>int_array_enum</> produces the same results
118 SELECT left, right FROM one_to_many WHERE left = <replaceable>item</>;
122 The difference is that the query against the summary table has to get
123 only one row from the table, whereas the direct query against
124 <structname>one_to_many</> must index scan and fetch a row for each entry.
128 On one system, an <command>EXPLAIN</> showed a query with a cost of 8488 was
129 reduced to a cost of 329. The original query was a join involving the
130 <structname>one_to_many</> table, which was replaced by:
134 SELECT right, count(right) FROM
135 ( SELECT left, int_array_enum(right) AS right
136 FROM summary JOIN (SELECT left FROM left_table WHERE left = <replaceable>item</>) AS lefts
137 ON (summary.left = lefts.left)