2010-12-27 23 views
0

Grüße,MySQL Group_concat Problem

Ich habe ein sehr heikeles Problem mit der Group_concat Funktion und ich bin für einige Tage ohne Erfolg zu denken, wie es zu lösen.

Es gibt 3 Tabellen:

tasks     task_tag     tag  
+---------+----------+ +---------+----------+ +---------+----------+ 
| task_id | data | | task_id | tag_id | | tag_id | name | 
+---------+----------+ +---------+----------+ +---------+----------+ 
|  1 | task 1 | | 1 | 5  | | 5 | work | 
|  2 | task 2 | | 1 | 7  | | 6 | school | 
|  3 | task 3 | | 2 | 6  | | 7 | home | 
+---------+----------+ +---------+----------+ +---------+----------+ 

Wenn alle Aufgaben abgerufen werden müssen, mit allen Tags, die sie mit als Ergebnisspalte verbunden sind, gibt es kein Problem mit der folgenden Abfrage:

SELECT t.task_id, t.data, GROUP_CONCAT(tg.name) AS tags 
FROM tasks t 
LEFT JOIN task_tag tt ON tt.task_id = t.task_id 
LEFT JOIN tag tg ON tg.tag_id = tt.tag_id 
GROUP BY t.task_id 

result 
+---------+-----------+-------------+ 
| task_id | data  | tags  | 
+---------+-----------+-------------+ 
| 1 | task 1 | work,home | 
| 2 | task 2 | school  | 
| 3 | task 3 | NULL  | 
+---------+-----------+-------------+ 

Das Problem ist, wenn ich die Aufgaben von einem EXACT-Tag auswählen muss, aber ich muss immer noch die Tags-Spalte mit allen zugeordneten Tags der Aufgaben beibehalten. Ich versuche mit der folgenden Abfrage, aber da das Ergebnis durch WHERE tag_id = 5 begrenzt ist, ruft die group_concat-Funktion nur das Tag mit ID = 5, z. „Arbeit“:

SELECT t.task_id, t.data, GROUP_CONCAT(tg.name) AS tags 
FROM tasks t 
LEFT JOIN task_tag tt ON tt.task_id = t.task_id 
LEFT JOIN tag tg ON tg.tag_id = tt.tag_id 
WHERE tg.tag_id = 5 
GROUP BY t.task_id 

result 
+---------+-----------+-------------+ 
| task_id | data |  tags | 
+---------+-----------+-------------+ 
| 1 | task 1 |  work | 
+---------+-----------+-------------+ 

Das Ergebnis, das ich zu erreichen bin versucht:

result 
+---------+-----------+-------------+ 
| task_id | data  |  tags | 
+---------+-----------+-------------+ 
| 1 | task 1 | work,home | 
+---------+-----------+-------------+ 

Vielen Dank für irgendwelche Vorschläge, wie dies zu lösen!

Antwort

2

Sie können dies tun, indem Sie Ihre erste Abfrage Modifizieren einer where-Klausel mit einer Unterabfrage enthalten:

SELECT t.task_id, t.data, GROUP_CONCAT(tg.name) AS tags 
FROM tasks t 
LEFT JOIN task_tag tt ON tt.task_id = t.task_id 
LEFT JOIN tag tg ON tg.tag_id = tt.tag_id 
WHERE t.task_id IN (SELECT task_id FROM task_tags WHERE tag_id=5) 
GROUP BY t.task_id 
+0

Vielen Dank! Ihre Abfrage scheint die schnellste der drei Antworten mit meinen Testdaten zu sein, das sind 200.000 Aufgaben, 1000 Tags, 10.000 task_tag und das Tag, gegen das ich teste, hat 1000 Aufgaben damit verbunden. Sicherlich sind es nicht absolut reale Daten, aber Ihre Abfrage ist auch am einfachsten zu machen :) – middlehut

1

Wenn ich verstehe, was Sie suchen, ich denke, das die Art von Ergebnissen führt Sie wurden vorstellen:

SELECT tasks.task_id, tasks.data, GROUP_CONCAT(tag.name) AS tags 
FROM tag AS looking_for 
JOIN task_tag AS first_tt ON first_tt.tag_id = looking_for.tag_id 
JOIN tasks ON tasks.task_id = task_tag.task_id 
JOIN task_tag AS second_tt ON second_tt.task_id = tasks.task_id 
JOIN tag ON tag.tag_id = second_tt.tag_id 
WHERE looking_for.tag_id = 5 
GROUP BY tasks.task_id 

Es ist mit dem ersten Tag beginnt der Sie gesucht haben, bahnt sich seinen Weg zurück in die Aufgabe zugeordnet, und dann JOINs für alle Tags für diese Aufgabe.

1

Verwenden Sie einen anstelle einer WHERE MIT, da eine WHERE-Klausel für jede einzelne Zeile lautet:

SELECT t.task_id, t.data, GROUP_CONCAT(tg.name) AS tags 
FROM tasks t 
LEFT JOIN task_tag tt ON tt.task_id = t.task_id 
LEFT JOIN tag tg ON tg.tag_id = tt.tag_id 
GROUP BY t.task_id 
HAVING Count(IF(tg.tag_id = 5,1,NULL)) > 0