Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1r5dtj-00EKom-Sk for pgsql-docs@arkaria.postgresql.org; Wed, 22 Nov 2023 03:27:32 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1r5dtg-004JRT-D5 for pgsql-docs@arkaria.postgresql.org; Wed, 22 Nov 2023 03:27:28 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1r5dtg-004JRL-59 for pgsql-docs@lists.postgresql.org; Wed, 22 Nov 2023 03:27:28 +0000 Received: from momjian.us ([72.94.173.45]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1r5dtc-007iLR-Fj for pgsql-docs@postgresql.org; Wed, 22 Nov 2023 03:27:27 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=momjian.us; s=2023062407; h=In-Reply-To:Content-Transfer-Encoding:Content-Type: MIME-Version:References:Message-ID:Subject:Cc:To:From:Date:Sender:Reply-To: Content-ID:Content-Description; bh=P7T7OkGnKyMAypsaZpqzWOjDuHRGCdgaLmvdBaT0or8=; b=Rn4K6WpSm0+mIqUwTO5lRfoCzc YZLmURcxR7OGqDgaYvb7wUFUTwIw5W/uOcop8/gTQ+Unik27O+3jhuSR7MLbnAfr0sTqYyHxEea+K mK6aG+CZqSGyMZJT0UlfWzd9OKAMliADVGKG8BqQWn2+qnRyzgCuaAteTgYY15x5vE59XuuVWnx6b w70ZZw2tXGWryL90KoRV/iFPJHfm5EIwToA3BjAJut4r2WcZQyW9ggA/0D8Sz/Oi+3TgRzjpRU2GO X41+ppFAkJxZ98XXCD7sSAv27FTVrsuXEQk556cCpQ0hwoia8nmJlxZymkNvhPiaUCbm0ZwKgbAqS DxXk4psA==; Received: from bruce by momjian.us with local (Exim 4.96) (envelope-from ) id 1r5dta-008BRL-1k; Tue, 21 Nov 2023 22:27:22 -0500 Date: Tue, 21 Nov 2023 22:27:22 -0500 From: Bruce Momjian To: Christophe Courtois Cc: Tom Lane , pgsql-docs@postgresql.org Subject: Re: [DOCS] intagg.sgml: example wrongly named and does not compile Message-ID: References: <15516.1492789516@sss.pgh.pa.us> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="XhpreqLVcPsF11jz" Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --XhpreqLVcPsF11jz Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit On Fri, Apr 21, 2017 at 06:07:13PM +0200, Christophe Courtois wrote: > Le 21/04/2017 à 17:45, Tom Lane a écrit : > > Christophe Courtois writes: > >> I've found out that the example in intagg.sgml is wrongly named: the > >> one-to-many table is a many-to-many. > > Well, it'd depend on how it was used. The example clearly intends that > > it be one-to-many, and I'm not sure it still makes sense without that > > restriction. Maybe better to add a unique constraint on > > one_to_many(left)? > > Perhaps the whole example can be simplified to get rid of the "left" > table, but I didn't intend to rewrite it. > > >> And my colleague Thibaut Madeleine has seen that the "CREATE TABLE > >> right" and "CREATE TABLE left" examples cannot compile due to the > >> reserved words. > > Ouch. Shows you how old this module is :-( > > Indeed. > > >> I propose the attached patch to fix that. > > Um, the attached file seems empty from here. > > Ooops, sorry. It is attached. I like this six year old patch so would like to apply it to master, attached. -- Bruce Momjian https://momjian.us EDB https://enterprisedb.com Only you can decide what is important to you. --XhpreqLVcPsF11jz Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="agg.diff" diff --git a/doc/src/sgml/intagg.sgml b/doc/src/sgml/intagg.sgml index 44a766eb4b..29e74ce146 100644 --- a/doc/src/sgml/intagg.sgml +++ b/doc/src/sgml/intagg.sgml @@ -54,20 +54,22 @@ Sample Uses - Many database systems have the notion of a one to many table. Such a table + Many database systems have the notion of a many to many table. Such a table usually sits between two indexed tables, for example: -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); +CREATE TABLE left_table (id INT PRIMARY KEY, ...); +CREATE TABLE right_table (id INT PRIMARY KEY, ...); +CREATE TABLE many_to_many(id_left INT REFERENCES left_table, + id_right INT REFERENCES right_table); It is typically used like this: -SELECT right.* from right JOIN one_to_many ON (right.id = one_to_many.right) - WHERE one_to_many.left = item; +SELECT right_table.* +FROM right_table JOIN many_to_many ON (right_table.id = many_to_many.id_right) +WHERE many_to_many.id_left = item; 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) Now, this methodology can be cumbersome with a very large number of - entries in the one_to_many table. Often, + entries in the many_to_many table. Often, a join like this would result in an index scan and a fetch for each right hand entry in the table for a particular left hand entry. If you have a very dynamic system, there is not much you @@ -85,9 +87,9 @@ SELECT right.* from right JOIN one_to_many ON (right.id = one_to_many.right) CREATE TABLE summary AS - SELECT left, int_array_aggregate(right) AS right - FROM one_to_many - GROUP BY left; + SELECT id_left, int_array_aggregate(id_right) AS rights + FROM many_to_many + GROUP BY id_left; This will create a table with one row per left item, and an array @@ -95,33 +97,35 @@ CREATE TABLE summary AS the array; that's why there is an array enumerator. You can do -SELECT left, int_array_enum(right) FROM summary WHERE left = item; +SELECT id_left, int_array_enum(rights) FROM summary WHERE id_left = item; The above query using int_array_enum produces the same results as -SELECT left, right FROM one_to_many WHERE left = item; +SELECT id_left, id_right FROM many_to_many WHERE id_left = item; The difference is that the query against the summary table has to get only one row from the table, whereas the direct query against - one_to_many must index scan and fetch a row for each entry. + many_to_many must index scan and fetch a row for each entry. On one system, an EXPLAIN showed a query with a cost of 8488 was reduced to a cost of 329. The original query was a join involving the - one_to_many table, which was replaced by: + many_to_many table, which was replaced by: -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) +SELECT id_right, count(id_right) FROM + ( SELECT id_left, int_array_enum(rights) AS id_right + FROM summary + JOIN (SELECT id FROM left_table + WHERE id = item) AS lefts + ON (summary.id_left = lefts.id) ) AS list - GROUP BY right + GROUP BY id_right ORDER BY count DESC; --XhpreqLVcPsF11jz--