2008-10-02 2 views
10

태그가이고 이 contentid가 인 두 개의 태그가있는 "태그"테이블이 있다고 가정합니다. 각 행은 콘텐츠에 할당 된 태그를 나타냅니다.SQL 쿼리 : 하위 쿼리 대신 여러 행에 대해 "AND"시뮬레이션

: 나는 나에게 tagids (334), (338) 태그 콘텐츠의 모든 조각의 콘텐츠 ID를 줄 것이다 쿼리 및 342

이 될 것이라고 할 수있는 "쉬운"방법 (의사를) 원하는

select contentid from tags where tagid = 334 and contentid in (
    select contentid from tags where tagid = 338 and contentid in (
     select contentid from tags where tagid = 342 
    ) 
) 

그러나 내 직감은 나에게 더 빠르고 더 확장 가능한 방법이 있음을 알립니다. 예를 들어, 12 개의 태그 교차를 찾으려면 어떻게해야합니까? 이것은 신속하게 끔찍한 얻을 수 있습니다. 어떤 아이디어?

편집 : 이것은 this excellent blog post에서도 다루어집니다. 내가 생각할 수있는

답변

24
SELECT contentID 
FROM tags 
WHERE tagID in (334, 338, 342) 
GROUP BY contentID 
HAVING COUNT(DISTINCT tagID) = 3 


--In general 
SELECT contentID 
FROM tags 
WHERE tagID in (...) --taglist 
GROUP BY contentID 
HAVING COUNT(DISTINCT tagID) = ... --tagcount 
+0

그게 전부입니다. 비록 tagid, contentid가 유일하다면, 아마도 DISTINCT는 COUNT (DISTINCT tagID) – tzot

+0

에 필요하지 않을 것입니다. 매우 똑똑한 솔루션이지만 SQL2000 설치시에는 조정이 필요합니다. select 절에 집계가 없으면 "having"을 사용할 수 없습니다. 그래도 충분히 쉽게 해결할 수 있습니다. –

+0

이 작업은 MySQL뿐만 아니라 Oracle에서도 가능합니까? –

1

유일한 다른 방법은 다음과 같습니다

select a.contentid from tags a 
inner join tags b on a.contentid = b.contentid and b.tagid=334 
inner join tags c on a.contentid = c.contentid and c.tagid=342 
where a.tagid=338 
-1

SQL의 어떤 종류의? 미시시피 SQL 서버, 오라클, MySQL은? 이 더 나은 경우 나도 몰라

select contentid from tags where tagid IN (334,338,342) 
+1

아니요, 3 개의 태그에있는 모든 기사를 제공 할 것입니다. 그는 동일한 3 개의 태그가있는 모든 기사를 원합니다. – albertein

+0

예, 당신이 맞다. David B가 그것을 못 박았습니다. – Meff

0

하지만

select contentid from tags where tagid = 334 
intersect 
select contentid from tags where tagid = 338 
intersect 
select contentid from tags where tagid = 342 

당신은 그것을 구축해야 할 것보다 유지 보수 수 있습니다 : SQL 서버에서

이에 동일시하지 않는다 동적으로 원래 솔루션만큼 나쁘지는 않을 것입니다.

2

매우 큰 개체 및 태그 데이터베이스에서 나를 위해 훨씬 빠르게 작업 한 솔루션이 있습니다. 이것은 3 개의 태그가 교차하는 예입니다. 그것은 단지 체인 많은 사람들이 동일한 개체를 나타 내기 위해 객체 태그 테이블 (objtags)에 조인하고 WHERE 절에 태그 ID를 규정 :이 빠르게 실행하는 이유

SELECT w0.objid 

FROM  objtags t0 
INNER JOIN objtags t1 ON t1.objid=t0.objid 
INNER JOIN objtags t2 ON t2.objid=t1.objid 

WHERE t0.tagid=512 
    AND t1.tagid=256 
    AND t2.tagid=128 

나는 아무 생각이 없습니다. 그것은 MusicBrainz 서버의 검색 코드에서 영감을 얻었습니다. Postgres에서이 작업을 수행 할 때 대개 HAVING COUNT(...) 솔루션보다 8 ~ 10 배 빨라졌습니다.

+0

집계 대신 집합 교차를 사용하여 세 값이 모두 적용되는지 여부를 결정합니다. 덜 스 래싱. 멋지다. 나는 생각했다. –