5454 <title>Sample Uses</title>
5555
5656 <para>
57- Many database systems have the notion of a one to many table. Such a table
57+ Many database systems have the notion of a many to many table. Such a table
5858 usually sits between two indexed tables, for example:
5959
6060<programlisting>
61- CREATE TABLE left (id INT PRIMARY KEY, ...);
62- CREATE TABLE right (id INT PRIMARY KEY, ...);
63- CREATE TABLE one_to_many(left INT REFERENCES left, right INT REFERENCES right);
61+ CREATE TABLE left_table (id INT PRIMARY KEY, ...);
62+ CREATE TABLE right_table (id INT PRIMARY KEY, ...);
63+ CREATE TABLE many_to_many(id_left INT REFERENCES left_table,
64+ id_right INT REFERENCES right_table);
6465</programlisting>
6566
6667 It is typically used like this:
6768
6869<programlisting>
69- SELECT right.* from right JOIN one_to_many ON (right.id = one_to_many.right)
70- WHERE one_to_many.left = <replaceable>item</replaceable>;
70+ SELECT right_table.*
71+ FROM right_table JOIN many_to_many ON (right_table.id = many_to_many.id_right)
72+ WHERE many_to_many.id_left = <replaceable>item</replaceable>;
7173</programlisting>
7274
7375 This will return all the items in the right hand table for an entry
@@ -76,7 +78,7 @@ SELECT right.* from right JOIN one_to_many ON (right.id = one_to_many.right)
7678
7779 <para>
7880 Now, this methodology can be cumbersome with a very large number of
79- entries in the <structname>one_to_many </structname> table. Often,
81+ entries in the <structname>many_to_many </structname> table. Often,
8082 a join like this would result in an index scan
8183 and a fetch for each right hand entry in the table for a particular
8284 left hand entry. If you have a very dynamic system, there is not much you
@@ -85,43 +87,45 @@ SELECT right.* from right JOIN one_to_many ON (right.id = one_to_many.right)
8587
8688<programlisting>
8789CREATE TABLE summary AS
88- SELECT left , int_array_aggregate(right ) AS right
89- FROM one_to_many
90- GROUP BY left ;
90+ SELECT id_left , int_array_aggregate(id_right ) AS rights
91+ FROM many_to_many
92+ GROUP BY id_left ;
9193</programlisting>
9294
9395 This will create a table with one row per left item, and an array
9496 of right items. Now this is pretty useless without some way of using
9597 the array; that's why there is an array enumerator. You can do
9698
9799<programlisting>
98- SELECT left , int_array_enum(right ) FROM summary WHERE left = <replaceable>item</replaceable>;
100+ SELECT id_left , int_array_enum(rights ) FROM summary WHERE id_left = <replaceable>item</replaceable>;
99101</programlisting>
100102
101103 The above query using <function>int_array_enum</function> produces the same results
102104 as
103105
104106<programlisting>
105- SELECT left, right FROM one_to_many WHERE left = <replaceable>item</replaceable>;
107+ SELECT id_left, id_right FROM many_to_many WHERE id_left = <replaceable>item</replaceable>;
106108</programlisting>
107109
108110 The difference is that the query against the summary table has to get
109111 only one row from the table, whereas the direct query against
110- <structname>one_to_many </structname> must index scan and fetch a row for each entry.
112+ <structname>many_to_many </structname> must index scan and fetch a row for each entry.
111113 </para>
112114
113115 <para>
114116 On one system, an <command>EXPLAIN</command> showed a query with a cost of 8488 was
115117 reduced to a cost of 329. The original query was a join involving the
116- <structname>one_to_many </structname> table, which was replaced by:
118+ <structname>many_to_many </structname> table, which was replaced by:
117119
118120<programlisting>
119- SELECT right, count(right) FROM
120- ( SELECT left, int_array_enum(right) AS right
121- FROM summary JOIN (SELECT left FROM left_table WHERE left = <replaceable>item</replaceable>) AS lefts
122- ON (summary.left = lefts.left)
121+ SELECT id_right, count(id_right) FROM
122+ ( SELECT id_left, int_array_enum(rights) AS id_right
123+ FROM summary
124+ JOIN (SELECT id FROM left_table
125+ WHERE id = <replaceable>item</replaceable>) AS lefts
126+ ON (summary.id_left = lefts.id)
123127 ) AS list
124- GROUP BY right
128+ GROUP BY id_right
125129 ORDER BY count DESC;
126130</programlisting>
127131 </para>
0 commit comments