6 <indexterm zone=
"intagg">
7 <primary>intagg
</primary>
11 The
<filename>intagg
</filename> module provides an integer aggregator and an
12 enumerator.
<filename>intagg
</filename> is now obsolete, because there
13 are built-in functions that provide a superset of its capabilities.
14 However, the module is still provided as a compatibility wrapper around
15 the built-in functions.
19 <title>Functions
</title>
22 The aggregator is an aggregate function
23 <function>int_array_aggregate(integer)<
/>
24 that produces an integer array
25 containing exactly the integers it is fed.
26 This is a wrapper around
<function>array_agg<
/>,
27 which does the same thing for any array type.
31 The enumerator is a function
32 <function>int_array_enum(integer[])<
/>
33 that returns
<type>setof integer<
/>. It is essentially the reverse
34 operation of the aggregator: given an array of integers, expand it
35 into a set of rows. This is a wrapper around
<function>unnest<
/>,
36 which does the same thing for any array type.
42 <title>Sample Uses
</title>
45 Many database systems have the notion of a one to many table. Such a table
46 usually sits between two indexed tables, for example:
50 CREATE TABLE left (id INT PRIMARY KEY, ...);
51 CREATE TABLE right (id INT PRIMARY KEY, ...);
52 CREATE TABLE one_to_many(left INT REFERENCES left, right INT REFERENCES right);
56 It is typically used like this:
60 SELECT right.* from right JOIN one_to_many ON (right.id = one_to_many.right)
61 WHERE one_to_many.left =
<replaceable>item<
/>;
65 This will return all the items in the right hand table for an entry
66 in the left hand table. This is a very common construct in SQL.
70 Now, this methodology can be cumbersome with a very large number of
71 entries in the
<structname>one_to_many<
/> table. Often,
72 a join like this would result in an index scan
73 and a fetch for each right hand entry in the table for a particular
74 left hand entry. If you have a very dynamic system, there is not much you
75 can do. However, if you have some data which is fairly static, you can
76 create a summary table with the aggregator.
80 CREATE TABLE summary as
81 SELECT left, int_array_aggregate(right) AS right
87 This will create a table with one row per left item, and an array
88 of right items. Now this is pretty useless without some way of using
89 the array; that's why there is an array enumerator. You can do
93 SELECT left, int_array_enum(right) FROM summary WHERE left =
<replaceable>item<
/>;
97 The above query using
<function>int_array_enum<
/> produces the same results
102 SELECT left, right FROM one_to_many WHERE left =
<replaceable>item<
/>;
106 The difference is that the query against the summary table has to get
107 only one row from the table, whereas the direct query against
108 <structname>one_to_many<
/> must index scan and fetch a row for each entry.
112 On one system, an
<command>EXPLAIN<
/> showed a query with a cost of
8488 was
113 reduced to a cost of
329. The original query was a join involving the
114 <structname>one_to_many<
/> table, which was replaced by:
118 SELECT right, count(right) FROM
119 ( SELECT left, int_array_enum(right) AS right
120 FROM summary JOIN (SELECT left FROM left_table WHERE left =
<replaceable>item<
/>) AS lefts
121 ON (summary.left = lefts.left)