2010-12-15 117 views
37

Je rencontre un problème avec la fonction "GROUP_CONCAT" de MySQL. Je vais illustrer mon problème à l'aide d'une simple base de données help desk:MySQL: GROUP_CONCAT avec LEFT JOIN

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 help desk a deux billets, chacune avec deux entrées de solution. Mon but 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. Ceci est l'instruction SELECT 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 il est de retour 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 est de retour les informations de billet 1 avec les deux billets de 1 et de les entrées de solution de ticket 2.

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

Répondre

71

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 

Autre:

SELECT t.*, 
      (SELECT GROUP_CONCAT(s.soution) 
      FROM SOLUTIONS s 
      WHERE s.ticket_id = t.ticket_id) AS combinedsolutions 
    FROM TICKETS t 
+1

Cela fonctionne! Je vous remercie! – Nick

+3

Mais pourquoi la méthode de Nick ne fonctionne-t-elle pas? Ce n'est évidemment pas le cas, mais il semble que ce devrait être le cas. Pouvez-vous m'expliquer? – pbarney

+0

Jusqu'à présent, je comprends que group_contact ne se soucie pas des parties de la requête, il regroupe tous les résultats intermédiaires. – jnovacho

1

Je pense que le commentaire de @Dylan est la plus simple Valade réponse donc je l'afficher comme une autre réponse: il suffit d'ajouter un GROUP BY Tickets.id à SELECT de l'OP devrait résoudre le problème. Il a fixé mon propre problème. Cependant, pour les bases de données qui ne sont pas petites, la réponse acceptée, en particulier s'il y a des prédicats sur Tickets.id ne semble pas impliquer une analyse de table totale et donc si le paragraphe précédent renvoie les bons résultats, il semble être beaucoup moins efficace dans mon cas.