2010-12-27 19 views
0

挨拶、MySQLのGROUP_CONCAT問題

私はGROUP_CONCAT機能を備えた非常にトリッキーな問題を抱えていると私はそれを解決する方法を、無成功を収めていくつかの日のために考えています。

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  | 
+---------+-----------+-------------+ 

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 | 
+---------+----------+ +---------+----------+ +---------+----------+ 

すべてのタスクが、彼らは結果列として関連付けられているすべてのタグで、取得する必要がある、次のクエリに問題がない:

は、3つのテーブルがあります

問題は、1つのEXACTタグからタスクを選択する必要がある場合ですが、タスクの関連タグすべてでタグ列を保持する必要がある場合もあります。次のクエリを試してみますが、結果はWHERE tag_id = 5によって制限されるため、group_concat関数はid = 5のタグだけを取得します。 「仕事」:

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 | 
+---------+-----------+-------------+ 

私が達成しようとしている結果は次のとおりです。

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

は、これを解決する方法上の任意の提案をありがとうございました!

答えて

2

あなたは、サブクエリとwhere句含まれるようにあなたの最初のクエリを変更することによってこれを行うことができます。

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

ありがとうございます!あなたのクエリは200.000のタスク、1000のタグ、10.000のtask_tag、私がテストしているタグに1000個のタスクが接続されているという私のテストデータの3つの回答から最も速いと思われます。確かにそれは本当に本当のデータではありませんが、あなたのクエリはまた、行うのが最も簡単です:) – middlehut

1

私はあなたが探しているものを理解していれば、私は、これはあなたが想像した結果の並べ替えを生成思う:

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 

それは、あなたが探していた最初のタグで始まりバックにそのように動作しますそのタスクのすべてのタグにJOINします。

1

使用をWHERE句はすべての単一の行のためになるので、代わりにWHEREのHAVING:

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