PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 17 RC1 » Annexes » Modules et extensions supplémentaires fournis » intagg -- agrégateur et énumérateur d'entiers

F.18. intagg -- agrégateur et énumérateur d'entiers #

Le module intagg fournit un agrégateur d'entiers et un énumérateur. intagg est maintenant obsolète car il existe des fonctions natives qui fournissent les mêmes fonctionnalités et au-delà. Néanmoins, le module est toujours disponible pour la compatibilité et utilise ces fonctions natives.

F.18.1. Fonctions #

L'agrégateur est une fonction d'agrégat int_array_aggregate(integer) qui produit un tableau d'entiers contenant exactement les entiers fournis en argument. Cette fonction appelle array_agg, qui fait la même chose pour n'importe quel type de tableau.

L'énumérateur est une fonction int_array_enum(integer[]) qui renvoie setof integer. C'est essentiellement une opération inverse de l'agrégateur : elle développe un tableau d'entiers en un ensemble de lignes. Cette fonction utilise unnest, qui fait la même chose pour n'importe quel type de tableau.

F.18.2. Exemples d'utilisation #

Un grand nombre de bases de données utilisent la notion de table « plusieurs vers plusieurs » (many to many). Ce type de table se trouve habituellement entre deux tables indexées, par exemple :

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);
  

C'est habituellement utilisé de cette façon :

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;
  

Cela renverra tous les éléments de la table de droite pour un enregistrement donné de la table de gauche. C'est une construction très courante en SQL.

Cette méthode devient complexe lorsqu'il existe de nombreuses entrées dans la table many_to_many. Souvent, une jointure de ce type résulte en un parcours d'index et une récupération de chaque enregistrement de la table de droite pour une entrée de la table de gauche. Sur un système très dynamique, il n'y a pas grand chose à faire. Au contraire, lorsqu'une partie des données est statique, une table de résumé peut être créée par agrégation.

CREATE TABLE summary AS
  SELECT id_left, int_array_aggregate(id_right) AS rights
  FROM many_to_many
  GROUP BY id_left;
  

Ceci crée une table avec une ligne par élément gauche et un tableau d'éléments droits. Sans un moyen d'utiliser ce tableau, c'est à peu près inutilisable, d'où l'énumérateur.

Exemple :

SELECT id_left, int_array_enum(rights) FROM summary WHERE id_left = item;
  

La requête ci-dessus, qui utilise int_array_enum, produit les mêmes résultats que celle-ci :

SELECT id_left, id_right FROM many_to_many WHERE id_left = item;
  

Ici la requête sur la table de résumé ne récupère qu'une ligne de la table alors que la requête directe à many_to_many doit faire un parcours d'index et récupérer une ligne par enregistrement.

Sur une instance, un EXPLAIN a montré qu'une requête avec un coût de 8488 a été réduite à un coût de 329. La requête originale était une jointure impliquant la table many_to_many, remplacée par :

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 id_right
  ORDER BY count DESC;