2010-12-27 5 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 개 테이블이 있습니다

문제는 하나의 EXACT 태그에서 작업을 선택해야하지만 모든 작업 관련 태그가있는 태그 열을 보존해야하는 경우입니다. 다음 쿼리로 시도하지만 결과는 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 개의 작업이 연결되어있는 테스트 데이터의 세 가지 답변 중에서 가장 빠른 것 같습니다. 확실히 그것은 절대적으로 실제 데이터가 아니지만 쿼리가 또한 가장 간단합니다 :) – 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 

는 다시 그것의 방법을 작동을 해당 작업에 대한 모든 태그에 대해 조인을 수행하십시오.

1

사용 A A 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