2010-12-10 2 views
2

저는 Postgresql을 사용하고 있습니다. 항목 테이블, 태그 테이블 및 항목과 많은 태그를 연결하는 테이블이 있습니다. 2 개 (또는 그 이상)의 태그와 일치하는 항목을 선택해야합니다.조인 된 테이블에서 둘 이상의 값이 주어진 세트와 일치하는 위치 선택

WHERE tag.name IN ('tag1', 'tag2')과 1을 초과하는 항목을 선택할 수 있습니다. MySQL에서 나는 WHERE x IN ALL (y, z)이라고 말할 수 있다고 생각하지만 작동하지 않습니다. pgsql입니다.

지금까지 내가 가진 최선의 방법은 하위 쿼리를 사용하여 두 테이블을 두 번 결합하는 것입니다. 이것은 분명히 많은 태그에서의 매칭에 맞지 않을 것이고 나는 가장 효율적인 접근법이 아닐 것이라고 확신합니다.

SELECT * 
FROM item 
JOIN (SELECT item.id FROM item 
     JOIN tagged on tagged.item=item.id 
     JOIN tag ON tag.id=taged.tag 
     WHERE tag.name='tagOne') p ON p.id=item.id 
JOIN tagged ON tagged.item=item.id 
JOIN tag ON tag.id=tagged.tag 
WHERE tag.name='tagTwo'` 

편집 : 난 아직도 물건을 테스트하지만, 하위 쿼리에서 이것을 사용하고 나의 위의 시도보다 더 나은 작동

SELECT item.id, count(tag2) AS relevance 
FROM item 
JOIN tagged tagged1 ON tagged1.item=item.id 
JOIN tag tag1 ON (tag1.id=tagged1.tag AND tag1.name='tag1') 
JOIN tagged tagged2 ON tagged2.item=item.id 
JOIN tag tag2 ON (tag2.id=tagged2.tag) 
WHERE tag2.name IN ('tag2', 'tag3') 
GROUP BY item.id 

여기에 요청 명확한 설명을 위해 일부 테이블 정의를의로 :

CREATE TABLE item (id serial, [...]); 
CREATE TABLE tag (id serial, name string UNIQUE); 
CREATE TABLE taged (tag int references tag(id), item int references item(id)); 
+1

참조 http://stackoverflow.com/questions/2161588/what-mysql-query-should-i-use-to-select-a-category-that-matches-all-my-criteria –

+1

나는 그렇지 않습니다. 'x ALL ALL (y, z)'가 MySQL에서 생각하는 것을 수행한다고 생각하십시오. 당신이 생각하고있는 것을 정확하게 볼 수 있도록 MySQL 예제를 제공 할 수 있습니까? –

+0

테이블/열 이름 지정이 다소 혼란스러운 경우 테이블 정의를 추가하면 질문이 향상됩니다. –

답변

4

가능한 접근 방식 (다수의) 3이다

select * 
from item 
where id in (select item 
       from tagged 
       group by item 
       having count(*)>=2); 
+0

나는 이것을 투표 할 것이나 아직 15 명의 담당자가 없다. 이 게시물을 좀 더 길게 남겨두고 아무 것도 게시하지 않는 한이 대답을 수락합니다. 감사합니다. –

+0

흠,이게 정말 효과가 있니? 아이디어가 꽤 멋지지만 ID를 ITEM에 조인하는 것은 정확하지 않습니다 - ID IN (항목 ...)에 대해서도 동일합니다. –

+0

@ item_ item 'item'은 테이블의 태그 이름입니다.'JOIN tagged on tagged '를 참조하십시오. item = item.id' 예를 들어 –

0

이해가 잘 안되지만 다음과 같이 간단히 쓸 수 있습니다.

WHERE tag.name IN (y) AND tag.name IN (z) 
당신은 단지 2 개 이상 일치를 원하는 경우

select * 
from item 
where id in (select tagged.item 
       from tagged join tag on(tag.id=taged.tag) 
       where tag.name in('tagOne', 'tagTwo') 
       group by tagged.item 
       having count(*)=2); 

select * 
from item join (select tagged.item, count(*) as numtags 
       from tagged join tag on(tag.id=taged.tag) 
       where tag.name in('tagOne', 'tagTwo') 
       group by tagged.item) using (id) 
where numtags=2; 

select * 
from item 
where id in (select tagged.item 
       from tagged join tag on(tag.id=taged.tag) 
       where tag.name='tagOne' 
       intersect 
       select tagged.item 
       from tagged join tag on(tag.id=taged.tag) 
       where tag.name='tagTwo'); 

하지만 당신은 태그 매치되는 괜찮다 : 여기

+0

결과가 0입니다. where 조건에 대해 테스트중인 행은 두 조건을 모두 충족시키지 않습니다. –

0

내가 사용하려면 형태 :

SELECT * 
FROM item 
WHERE EXISTS (SELECT 1 FROM tagged JOIN tag ON tag.id = tagged.tag 
       WHERE tag.name = 'tag1') 
     AND 
     EXISTS (SELECT 1 FROM tagged JOIN tag ON tag.id = tagged.tag 
       WHERE tag.name = 'tag2') 

당신은 "이 분명히 많은 태그를 일치로 확장되지 않습니다 내가 가장 효율적인 방법은 아니다 확신한다"고 주장 -하지만 사장님 소리 너 추측하고 있니?

+0

나는 "* 확장되지 않습니다"* 새 태그를 포함해야 할 때마다 추가/변경해야 할 SQL의 양을 나타냅니다. –

+0

효율성까지는 추측하고 있지만 a_horse_with_no_name은 정확합니다. 2 개 이상의 태그를 동일한 SQL과 일치시킬 수 있어야합니다. –

관련 문제