2014-01-12 2 views
0

질문 제목에 대해 유감스럽게 생각합니다. 더 명확한 방법으로 작성하는 방법을 모르겠습니다.Mysql : 주어진 값으로 table2의 여러 행을 결합하는 table1의 1 행

그래서, 나는 theree 테이블이 있습니다

  1. tracks가 포함를 id (트랙 ID) & name (트랙 이름)
  2. tagsid (태그 ID) & name (태그 이름)
  3. 을 포함
  4. , 포함 : track_id & tag_id

목록에 지정된 모든 태그 (예 : '바위', '팝'및 '댄스'태그가있는 모든 트랙을 한 번에 찾아야 함)가있는 모든 트랙을 찾아야합니다.

이전에 비슷한 문제가 발생했지만 적어도 하나 이상의 태그가 일치하는 모든 트랙을 찾았습니다. 그것은 아주 쉬웠다 :

SELECT tracks.* 
FROM tags 
INNER JOIN track_tags ON tags.id = track_tags.tag_id 
INNER JOIN tracks ON track_tags.track_id = tracks.id 
WHERE tags.name IN('pop', 'rock', 'dance') 
GROUP BY tracks.id 

그러나 목록에서 모든 태그와 정확히 일치하는 모든 트랙을 찾는 방법을 모른다.

모든 트랙과 모든 태그를 내 앱 및 필터 트랙에서 검색하는 것에 대해 생각해 보았습니다.하지만 그 중 상당수 (수십만 개)가 앱에서 페이지 매기기를 사용하고 있으며 LIMIT를 사용하여 쉽게 구현할 수 있습니다. 상위 쿼리.

아마 mysql 기능을 사용하여 다른 방법으로 수행 할 수 있습니까? 모든 태그가 포함 된 모든 트랙을 선택하고이를 앱 사이드에서 필터링하면 웹 서버가 죽어 버린다는 사실을 알게되었습니다.

답변

2

having 절이 사용하는 집계를 해결하는 가장 일반적인 방법 :

:

SELECT tracks.* 
FROM tags INNER JOIN 
    track_tags 
    ON tags.id = track_tags.tag_id INNER JOIN 
    tracks 
    ON track_tags.track_id = tracks.id 
GROUP BY tracks.id 
HAVING sum(tags.name = 'pop') > 0 and 
     sum(tags.name = 'rock') > 0 and 
     sum(tags.name = 'dance') > 0; 

이에 약간의 변화가 어디에서 필터링을 다음 세 가지 태그를 보는 것입니다

SELECT tracks.* 
FROM tags INNER JOIN 
    track_tags 
    ON tags.id = track_tags.tag_id INNER JOIN 
    tracks 
    ON track_tags.track_id = tracks.id 
WHERE tags.name IN('pop', 'rock', 'dance') 
GROUP BY tracks.id 
HAVING count(distinct tags.name) = 3; 
+0

와우. 나는 그것을 반드시 시도해야한다. 그것은 나의 인생을 구하는 것처럼 보이는 때가 처음입니다. 이 쿼리에는 많은 RAM이 필요합니다. 맞습니까? – avasin

+1

MySQL의 집계 쿼리는 외부 파일 정렬 알고리즘을 사용하는 경향이 있습니다. 그 (것)들은 일종의 천천히,하지만 당신은 귀하의 데이터에 그것을 시도해야합니다. –

+0

한 가지 더 질문 :이 검색어는 중복 된 트랙이 아니어야합니다. 모든 반환 된'tracks' 행은 논리적으로 고유해야합니다. – avasin

관련 문제