Outils personnels
Vous êtes ici : Accueil Base de données Group By dans un tableau avec PostgreSQL
Se connecter


Mot de passe oublié ?
Nouvel utilisateur ?
 

Group By dans un tableau avec PostgreSQL

Par Benjamin Poulain Dernière modification 14:18

Une petite "astuce" bien pratique pour PostgreSQL: comment agréger le résultat d'une projection dans un tableau?

Le problème qui se pose est le suivant: certaines requêtes doivent retourner un identifiant, et une liste de langues (2 à n) qui correspondent à l'identifiant. Comment agréger cette liste de taille variable et l'exploiter dans le reste des fonctions SQL? Grâce aux tableaux!

Pour les identifiants on a la table X:

id nom
1 Foo
2 Bar

Et pour les langues, la table LANGS:

X_id lang_name
1 fr_fr
1 en_us
2
fr_fr
2 es
2
en_gb

Il se trouve que PostgreSQL gère un type composite particulièrement pratique, les tableau (ARRAY). Un petit exemple:

$ select 5, '{1, 2, 3, 4}';
 ?column? |   ?column?   
----------+--------------
        5 | {1, 2, 3, 4}
(1 row)

Les tableaux ayant toute une série de fonction associée, c'est l'idéal pour gérer ce genre de données variables. Reste qu'il n'y a pas, par défaut, de fonction d'agrégationdans un tableau (donc pas de group by dans un array).

Heureusement, PostgreSQL nous permet de créer des fonctions d'agrégation, et c'est même mieux, la documentation nous dit comment résoudre notre problème!

On commence par créer la fonction d'agrégation:

CREATE AGGREGATE array_accum (anyelement)
(
    sfunc = array_append,
    stype = anyarray,
    initcond = '{}'
);

ou (pour PostgreSQL <= 8.1):

CREATE AGGREGATE array_accum (
    sfunc = array_append,
    basetype = anyelement,
    stype = anyarray,
    initcond = '{}'
);

Et on peut agréger des données variable dans notre tableau:

SELECT X.id, array_accum(LANGS.all_langs)
FROM X
     JOIN LANGS ON (X.id = LANGS.X_id)
GROUP BY X.id

Allez plus loin ', '.join(array)

Nous avons vu une utilisation bien jolie des tableaux et je vous propose de voir une autre fonctionnalité cool pour vos fonctions SQL. En Python, on peut utiliser join() sur une chaîne de caractère pour la concatainer de façon intélligente:

>>> liste_langue = ['fr_fr', 'en_us', 'es']
>>> print ', '.join(liste_langue)
"fr_fr, en_us, es"

Avec PostgreSQL et les tableaux, on fais exactement la même chose grâce à la fonction array_to_string().

Si je reprend l'exemple précédent, on peux faire

SELECT X.id, array_to_string(array_accum(LANGS.all_langs), ', ') as langs
FROM X
     JOIN LANGS ON (X.id = LANGS.X_id)
GROUP BY X.id

qui nous donne:

 X.id     |   langs   
----------+-------------------
        1 | fr_fr, en_us
        2 | fr_fr, es, en_gb

(1 row)
Actions sur le document