2011-09-14 5 views
0

현재 태그 클라우드 시스템을 작성 중입니다. 다 대다 SQL 선택

그래서 나는 다음과 같은 SQL 스키마 썼다 :

CREATE TABLE bookmark_model_bookmark (
    id INTEGER NOT NULL, 
    link VARCHAR(255), 
    title VARCHAR(140), 
    description TEXT, 
    PRIMARY KEY (id) 
); 

CREATE TABLE bookmark_model_tag (
    id INTEGER NOT NULL, 
    name VARCHAR(20), 
    PRIMARY KEY (id) 
); 

CREATE TABLE bookmark_tag (
    bookmark_model_bookmark_id INTEGER NOT NULL, 
    bookmark_model_tag_id INTEGER NOT NULL, 
    PRIMARY KEY (bookmark_model_bookmark_id, bookmark_model_tag_id), 
    CONSTRAINT bookmark_model_bookmark_tags_fk FOREIGN KEY(bookmark_model_bookmark_id) REFERENCES bookmark_model_bookmark (id), 
    CONSTRAINT bookmark_model_tag_bookmarks_fk FOREIGN KEY(bookmark_model_tag_id) REFERENCES bookmark_model_tag (id) 
); 

을 그리고 적은 양의 데이터로 채우기 : 가독성 측면에서

SELECT * FROM bookmark_model_bookmark; 

1|http://braindead.fr|braindead| 
2|http://example.fr|example|example text 

SELECT * FROM bookmark_model_tag; 

1|test 
2|braindead 
3|example 

SELECT * FROM bookmark_tag; 

1|1 
1|2 
2|1 
2|3 

:

  • 즐겨 찾기 # 1 braindead는 http://braindead.fr/을 참조하고 두 개의 태그가 있습니다 : "test"와 "braindead".
  • 북마크 # 2라는 이름의 예제는 http://example.fr/을 참조하며 "test"및 "example"에 태그를 지정해야합니다.

그래서 내 개발의 다음 단계는 선택한 태그 목록으로 태그가 지정된 책갈피에 링크 된 모든 태그를 선택하는 것입니다.

예를 들어 매개 변수 "test"에서 "braindead"와 "example"을 반환해야합니다. 둘 다 테스트 태그로 태그가 지정되어 있기 때문입니다.

"test"및 "braindead"매개 변수를 전달하는 경우 "test"및 "braindead"태그가있는 유일한 책갈피이므로 "braindead"만 쿼리에서 반환해야합니다.

SELECT * 
FROM bookmark_model_tag AS tag 
INNER JOIN bookmark_tag ON (bookmark_tag.bookmark_model_tag_id = tag.id) 
WHERE bookmark_tag.bookmark_model_bookmark_id IN (/* Here my subquery */); 

하지만 하위 쿼리를 찾을 수 없습니다. 나는 이런 식으로 시작해야한다 :

SELECT bookmark.id 
FROM bookmark_model_bookmark AS bookmark 
INNER JOIN bookmark_tag ON (bookmark.id = bookmark_tag.bookmark_model_bookmark_id) 
WHERE /* what to write here ? */ 

정확히 말하면, 내 쿼리의 입력 매개 변수는 태그 ID의 배열이다.

그래서 여기에 붙어 있습니다.

편집

내가하는 ORM (SQLAlchemy의)를 사용하여 내 쿼리를 작성, 그것은 다음과 같습니다 쿼리를 작성입니다 해요 :

이 여전히 문제가되는 경우
SELECT tag.id AS tag_id, tag.name AS tag_name, count(tag.id) AS count_1 
FROM tag, bookmark_tag, (
    SELECT bookmark.id AS id 
    FROM bookmark, bookmark_tag 
    WHERE bookmark.id = bookmark_tag.bookmark_id 
    AND bookmark_tag.tag_id IN (1, 2) 
    GROUP BY bookmark.id 
    HAVING count(bookmark.id) = 2) AS anon_1 
WHERE tag.id = bookmark_tag.tag_id 
AND bookmark_tag.bookmark_id = anon_1.id 
AND tag.id NOT IN (1, 2) 
GROUP BY tag.id 
+3

이것은 [Relational Division] (http://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/)입니다. 가장 일반적인 접근 방식은 'GROUP BY'와 'COUNT'인 것 같습니다. –

+0

내 where 절이 이제 "WHERE bookmark_tag.bookmark_model_tag_id IN ($ TAG_LIST_ID) GROUP BY bookmark.id HAVING count (*) == $ TAG_LIST_SIZE"가되었습니다. 그게 당신이 기대하는 것입니까? –

+0

예. 'bookmark_tag'에 고유 한 제약 조건이 있다고 가정하면 동일한 콤보에 대해 중복을 가질 수 없습니다. –

답변

0

확실하지하지만 쿼리는 다음과 같이 표시되어야합니다.

DECLARE @array TABLE(
    tag varchar(50) 
) 
INSERT INTO @array 
VALUES('test') 
INSERT INTO @array 
VALUES('braindead') 

select * from bookmark_model_bookmark 
where id in(
    select bookmark_model_bookmark_id FROM bookmark_tag x INNER JOIN bookmark_model_tag t ON t.id = x.bookmark_model_tag_id 
    where t.name in (select tag from @array) 
    group by bookmark_model_bookmark_id 
    having bookmark_model_bookmark_id >= (select count(0) from @array)) 

위 예제에서 나는 테이블을 사용했지만 쉼표 구분 된 문자열 입력은 비슷한 위치에서 끝납니다. 이것이 당신이 찾고 있던 것이거나 ive가 막대기의 틀린 끝을 얻은 경우에 저에게 알리는가 ??? 감사,

+0

사실 그것은 해결책입니다. 현재 솔루션으로 내 질문을 업데이트했습니다. –

+0

질문을 닫는 것이 좋습니다. 귀중한 시간을 낭비하는 사람들을 막으십시오. – Christo