54
54
<title>Sample Uses</title>
55
55
56
56
<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
58
58
usually sits between two indexed tables, for example:
59
59
60
60
<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);
64
65
</programlisting>
65
66
66
67
It is typically used like this:
67
68
68
69
<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>;
71
73
</programlisting>
72
74
73
75
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)
76
78
77
79
<para>
78
80
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,
80
82
a join like this would result in an index scan
81
83
and a fetch for each right hand entry in the table for a particular
82
84
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)
85
87
86
88
<programlisting>
87
89
CREATE 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 ;
91
93
</programlisting>
92
94
93
95
This will create a table with one row per left item, and an array
94
96
of right items. Now this is pretty useless without some way of using
95
97
the array; that's why there is an array enumerator. You can do
96
98
97
99
<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>;
99
101
</programlisting>
100
102
101
103
The above query using <function>int_array_enum</function> produces the same results
102
104
as
103
105
104
106
<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>;
106
108
</programlisting>
107
109
108
110
The difference is that the query against the summary table has to get
109
111
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.
111
113
</para>
112
114
113
115
<para>
114
116
On one system, an <command>EXPLAIN</command> showed a query with a cost of 8488 was
115
117
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:
117
119
118
120
<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)
123
127
) AS list
124
- GROUP BY right
128
+ GROUP BY id_right
125
129
ORDER BY count DESC;
126
130
</programlisting>
127
131
</para>
0 commit comments