La fonction GROUP_CONCAT en MySQL
Accueil Tags Recherche15 Janvier 2015
La fonction GROUP_CONCAT en MySQL
Connaissez-vous la fonctionGROUP_CONCAT
en MySQL ?
Présentation
Cette fonction permet de concaténer les valeurs non nulles d’un groupe. Ok… c’est un peu abstrait.
Prenons-donc un modèle de relation 1..*
courant pour cette présentation : Livre ~ Catégorie.
Voici de quoi avoir une base de test de votre côté :
CREATE TABLE livre (`id` int, `titre` varchar(50));
INSERT INTO livre (`id`, `titre`)
VALUES
(1, 'Le Seigneur des Anneaux'),
(2, 'Alice aux Pays des Merveilles');
CREATE TABLE categorie (`id` int, `libelle` varchar(50));
INSERT INTO categorie (`id`, `libelle`)
VALUES
(1, 'Fantastique'),
(2, 'Aventure'),
(3, 'Enfant'),
(4, 'Médiéval');
CREATE TABLE livrecategorie (`id_livre` int, `id_categorie` int);
INSERT INTO livrecategorie (`id_livre`, `id_categorie`)
VALUES
(1, 1),
(1, 2),
(1, 4),
(2, 1),
(2, 3);
Ici, je vais récupérer l’ensemble des catégories pour chaque livre :
SELECT
l.titre AS livre,
c.libelle AS categorie
FROM livre l
LEFT JOIN livrecategorie lc ON lc.id_livre = l.id
LEFT JOIN categorie c ON lc.id_categorie = c.id;
-- #-------------------------------#-------------#
-- # LIVRE # CATEGORIE #
-- #-------------------------------#-------------#
-- # Le Seigneur des Anneaux # Fantastique #
-- # Le Seigneur des Anneaux # Aventure #
-- # Le Seigneur des Anneaux # Médiéval #
-- # Alice aux Pays des Merveilles # Fantastique #
-- # Alice aux Pays des Merveilles # Enfant #
-- #-------------------------------#-------------#
Si on ne veut qu’une seule ligne par livre, il va falloir utiliser un GROUP BY
. Oui mais…
SELECT
l.titre AS livre,
c.libelle AS categorie
FROM livre l
LEFT JOIN livrecategorie lc ON lc.id_livre = l.id
LEFT JOIN categorie c ON lc.id_categorie = c.id
GROUP BY l.id;
-- #-------------------------------#-------------#
-- # LIVRE # CATEGORIE #
-- #-------------------------------#-------------#
-- # Le Seigneur des Anneaux # Fantastique #
-- # Alice aux Pays des Merveilles # Fantastique #
-- #-------------------------------#-------------#
On ne récupère en effet que la première ligne pour chaque livre. L’idéal serait de regrouper toutes les valeurs de c.libelle
pour un même l.id
, et de les concaténer.
C’est précisément le rôle de GROUP_CONCAT
, donc voici un exemple :
SELECT
l.titre AS livre,
GROUP_CONCAT(c.libelle) AS categories
FROM livre l
LEFT JOIN livrecategorie lc ON lc.id_livre = l.id
LEFT JOIN categorie c ON lc.id_categorie = c.id
GROUP BY l.id;
-- #-------------------------------#-------------------------------#
-- # LIVRE # CATEGORIES #
-- #-------------------------------#-------------------------------#
-- # Le Seigneur des Anneaux # Fantastique,Médiéval,Aventure #
-- # Alice aux Pays des Merveilles # Enfant,Fantastique #
-- #-------------------------------#-------------------------------#
Paramétrer la concaténation
Vous pouvez choisir de trier les résultats avec ORDER BY
:
SELECT
l.titre AS livre,
GROUP_CONCAT(c.libelle ORDER BY c.libelle) AS categories
FROM livre l
LEFT JOIN livrecategorie lc ON lc.id_livre = l.id
LEFT JOIN categorie c ON lc.id_categorie = c.id
GROUP BY l.id;
-- #-------------------------------#-------------------------------#
-- # LIVRE # CATEGORIES #
-- #-------------------------------#-------------------------------#
-- # Le Seigneur des Anneaux # Aventure,Fantastique,Médiéval #
-- # Alice aux Pays des Merveilles # Enfant,Fantastique #
-- #-------------------------------#-------------------------------#
Ou bien changer le caractère de séparation avec SEPARATOR
:
SELECT
l.titre AS livre,
GROUP_CONCAT(c.libelle SEPARATOR ' / ') AS categories
FROM livre l
LEFT JOIN livrecategorie lc ON lc.id_livre = l.id
LEFT JOIN categorie c ON lc.id_categorie = c.id
GROUP BY l.id;
-- #-------------------------------#-----------------------------------#
-- # LIVRE # CATEGORIES #
-- #-------------------------------#-----------------------------------#
-- # Le Seigneur des Anneaux # Fantastique / Médiéval / Aventure #
-- # Alice aux Pays des Merveilles # Enfant / Fantastique #
-- #-------------------------------#-----------------------------------#
Ou encore supprimer les doublons avec DISTINCT
. On cherche ici à récupérer toutes les catégories liées à au moins un livre, mais sans avoir de doublons dans les résultats
-- Sans DISTINCT
SELECT GROUP_CONCAT( c.libelle) AS categories
FROM livre l
LEFT JOIN livrecategorie lc ON lc.id_livre = l.id
LEFT JOIN categorie c ON lc.id_categorie = c.id;
-- #--------------------------------------------------#
-- # CATEGORIES #
-- #--------------------------------------------------#
-- # Fantastique,Aventure,Médiéval,Fantastique,Enfant #
-- #--------------------------------------------------#
-- Avec DISTINCT
SELECT GROUP_CONCAT(DISTINCT c.libelle) AS categories
FROM livre l
LEFT JOIN livrecategorie lc ON lc.id_livre = l.id
LEFT JOIN categorie c ON lc.id_categorie = c.id;
-- #--------------------------------------#
-- # CATEGORIES #
-- #--------------------------------------#
-- # Fantastique,Aventure,Médiéval,Enfant #
-- #--------------------------------------#
À présent, à vous de jouer pour trouver d’autres applications utiles !