web-dev-qa-db-fra.com

MySQL: GROUP_CONCAT avec LEFT JOIN

Je rencontre un problème avec la fonction "GROUP_CONCAT" de MySQL. Je vais illustrer mon problème en utilisant une simple base de données du service d'assistance:

CREATE TABLE Tickets (
 id INTEGER NOT NULL PRIMARY KEY,
 requester_name VARCHAR(255) NOT NULL,
 description TEXT NOT NULL);

CREATE TABLE Solutions (
 id INTEGER NOT NULL PRIMARY KEY,
 ticket_id INTEGER NOT NULL,
 technician_name VARCHAR(255) NOT NULL,
 solution TEXT NOT NULL,
 FOREIGN KEY (ticket_id) REFERENCES Tickets.id);

INSERT INTO Tickets VALUES(1, 'John Doe', 'My computer is not booting.');
INSERT INTO Tickets VALUES(2, 'Jane Doe', 'My browser keeps crashing.');
INSERT INTO Solutions VALUES(1, 1, 'Technician A', 'I tried to solve this but was unable to. I will pass this on to Technician B since he is more experienced than I am.');
INSERT INTO Solutions VALUES(2, 1, 'Technician B', 'I reseated the RAM and that fixed the problem.');
INSERT INTO Solutions VALUES(3, 2, 'Technician A', 'I was unable to figure this out. I will again pass this on to Technician B.');
INSERT INTO Solutions VALUES(4, 2, 'Technician B', 'I re-installed the browser and that fixed the problem.');

Notez que cette base de données du service d'assistance comporte deux tickets, chacun avec deux entrées de solution. Mon objectif est d'utiliser une instruction SELECT pour créer une liste de tous les tickets dans la base de données avec leurs entrées de solution corrospondantes. Voici l'instruction SELECT que j'utilise:

SELECT Tickets.*, GROUP_CONCAT(Solutions.solution) AS CombinedSolutions
FROM Tickets
LEFT JOIN Solutions ON Tickets.id = Solutions.ticket_id
ORDER BY Tickets.id;

Le problème avec l'instruction SELECT ci-dessus est qu'elle ne renvoie qu'une seule ligne:

id: 1
requester_name: John Doe
description: My computer is not booting.
CombinedSolutions: I tried to solve this but was unable to. I will pass this on to Technician B since he is more experienced than I am.,I reseated the RAM and that fixed the problem.,I was unable to figure this out. I will again pass this on to Technician B.,I re-installed the browser and that fixed the problem.

Notez qu'il renvoie les informations du ticket 1 avec les entrées de solution du ticket 1 et du ticket 2.

Qu'est-ce que je fais mal? Merci!

50
Nick

Utilisation:

   SELECT t.*,
          x.combinedsolutions
     FROM TICKETS t
LEFT JOIN (SELECT s.ticket_id,
                  GROUP_CONCAT(s.soution) AS combinedsolutions
             FROM SOLUTIONS s 
         GROUP BY s.ticket_id) x ON x.ticket_id = t.ticket_id

Alterner:

   SELECT t.*,
          (SELECT GROUP_CONCAT(s.soution)
             FROM SOLUTIONS s 
            WHERE s.ticket_id = t.ticket_id) AS combinedsolutions
     FROM TICKETS t
85
OMG Ponies

Je pense que le commentaire de @Dylan Valade est la réponse la plus simple, donc je le poste comme une autre réponse: simplement ajouter un GROUP BY Tickets.id au SELECT de l'OP devrait résoudre le problème. Cela a résolu mon propre problème.

Cependant, pour les bases de données qui ne sont pas petites, la réponse acceptée, surtout s'il y a des prédicats sur Tickets.id ne semble pas impliquer une analyse complète de la table et donc, alors que le paragraphe précédent renvoie les résultats corrects, il semble être beaucoup moins efficace dans mon cas. .

2
ghr

Il vous suffit d'ajouter un GROUP_BY:

SELECT Tickets.*, GROUP_CONCAT(Solutions.solution) AS CombinedSolutions FROM Tickets 
LEFT JOIN Solutions ON Tickets.id = Solutions.ticket_id 
GROUP_BY Tickets.id 
ORDER BY Tickets.id;
1
Frederic WOEHL