2012-03-11 5 views
2

많은 기사를 참조하는 테이블이 있는데이 테이블에는 해당 기사의 태그가 들어 있습니다. 이처럼 :매핑 행에서 기본 선택 SQL

tag text 
article_id bigint 

내가 태그 집합 모든 article_ids를 선택하려면,이 tag1, tag2로, TAG3하지만 기사는 tag4을 가지고 있다고 말한다, tag5도 첨부.

SELECT article_id 
FROM tag WHERE tag='tag1' 
INTERSECT 
SELECT article_id 
FROM tag 
WHERE tag='tag2' 
INTERSECT 
SELECT article_id 
FROM tag 
WHERE tag='tag3' 

을 그리고이를 것이다 :

나는이 일을 알고

SELECT article_id 
FROM tag 
WHERE tag IN ('tag1','tag2','tag3') 
GROUP BY article_id 
HAVING count(*) = 3 

그러나 나는이 작업을 수행 할 수있는 가장 효율적인 방법임을 확실하지 않다. 나는 또한 아래에 놀고있다, 그러나 지금 일하기 위하여 그것을 얻을 수 없다.

SELECT array_agg(tag) as arr, 
     article_id 
FROM tag 
GROUP BY article_id 
HAVING arr = {tag1,tag2,tag3} 

이것은 단지 다른 사람이 발생하는 것 INTERSECT이 경우에 가장 효율적인 쿼리 인 경우 궁금 해서요 공통의 문제처럼 보였다. 그것은 PostgreSQL을위한 것입니다.

+1

당신이 가장 효율적인 쿼리를 찾으려면, 그냥 약간 article_id를 HAVING array_agg (태그 BY 태그 : 텍스트 ORDER)에 의해 태그 그룹에서 SELECT article_id를 "로 작동 재 작성 할 때이'ANALZYE' –

답변

0

개인적으로 나는 두 번째 옵션을 좋아합니다. 그러나 PostgreSQL의 도구와 몇 가지 테스트 쿼리를 사용하여 어느 것이 가장 효율적인지 파악해야합니다. how to make array_agg() work like group_concat() from mySQL

+0

를 EXPLAIN 실행 = ARRAY [ 'tag1', 'tag2', 'tag3']; " 기사에 tag4가 있으면 찾지 못합니다.기본적으로 모든 항목이 배열에 있는지 확인하기 위해 누락 된 방법이 있습니까?하지만 배열이 완벽하게 일치하지 않습니다. – ehiller

1

나는 그냥 article_id보다 article에서 더 많은 열을 원하는 가정은 array_agg에 대한 정렬 순서를()를 지정해야하기 때문에

작성된 세 번째가 작동하지 않는 이유입니다. 하지만 쿼리 스타일을 많이 변경하지는 않습니다.

처리중인 것은 관계형 구분이라고합니다. 색인 생성 및 성능 테스트에 대한 조언을 포함하여 under this related question으로 볼 수있는 것처럼이 고양이를 껍질을 벗기는 방법에는 여러 가지가 있습니다.

내 개인 즐겨 찾기 (가장 빠른 중에서 가능성이 높다)는 다음과 같습니다

SELECT a.* 
FROM article a 
JOIN tag x USING (article_id) 
JOIN tag y USING (article_id) 
JOIN tag z USING (article_id) 
WHERE x.tag = 'tag1' 
AND y.tag = 'tag1' 
AND z.tag = 'tag3'; 

또는 : 세 번째 버전이 작동하지 않을 수있는 이유

SELECT a.* 
FROM article a 
WHERE EXISTS (
    SELECT * 
    FROM tag x 
    JOIN tag y USING (article_id) 
    JOIN tag z USING (article_id) 
    WHERE x.article_id = a.article_id 
    AND x.tag = 'tag1' 
    AND y.tag = 'tag2' 
    AND z.tag = 'tag3' 
    ); 

@ 데이비드 이미 설명했다. 그러나 색인을 사용할 수 없으며 다른 방법보다 진도가 느려질 수 있으므로 어쨌든 사용하지 마십시오. here.

0

마지막 변종에서는 배열 평등에 관심이 없습니다. 배열 봉쇄에 관심이 있으시면 HAVINGarr에 세 개의 태그가 모두 포함되어 있습니다.

그리고 array1이 포함 된 array2는 PostgreSQL에서 array1 @> array2입니다.

여전히 색인 생성 덕분에 Erwin의 대답이 성능상의 우승을 기대합니다.