2012-11-16 3 views
1

3 테이블 : books, book_categories, categories이 있습니다.다른 카테고리에 속하는 도서를 제외하고 한 카테고리의 모든 서적을 선택하십시오.

book_categories 테이블 "조인"bookscategories. 열은 id, book_id, category_id입니다.

그래서 하나의 책은 많은 범주에 속할 수 있으며 하나의 범주는 많은 책을 가질 수 있습니다.

에 속하는서만 제외하고 given_category에서 모든 서적을 검색하는 쿼리가 필요합니다. 예를 들어 카테고리 A의 모든 도서를 카테고리 B 또는 C에도 속하지 않는 경우에만 원합니다. Book.inserted 열을 기준으로 정렬 (정렬)해야합니다.

나는 두 개의 결합으로 given_category에서 모든 책을 얻는 방법을 알고 있지만 결과로 다른 카테고리의 책을 제외하는 방법을 알 수 없습니다. 검색 결과 페이지 매기기 때문에 PHP에서 필터 책을 사용할 수 없습니다. 당신이 의미하는 경우

답변

1
where 
    category_id = <given category> 
    and books.book_id not in 
(
select book_id from book_categories 
    where category_id in (<given set of cat>) 
) 
order by books.inserted 
+0

잘 작동하지만 매우 느리게 작동> 1 given_set의 요소 번호 : 그것뿐만 아니라 다른 카테고리에 속하는지 확인하기 위해 총을 계산 카테고리를 1 개만 제외하면 잘 작동합니다. – user606521

0

그래서, 다른 한 종류가 아니라에 있습니다

AND EXISTS(SELECT * FROM books b JOIN book_categories bc ON b.id = bc.book_id JOIN categories c ON bc.category_id = c.id AND c.id = 'A') 
AND NOT EXISTS(SELECT * FROM books b JOIN book_categories bc ON b.id = bc.book_id JOIN categories c ON bc.category_id = c.id AND c.id != 'A') 
0

내가이가 book_categories 항목 따라서, 독특한 것을 카운팅을 통해 달성 될 수 있다고 생각 조합 book_id & category_id은이 아닌 입니다. 대신 레코드를 제외 직접 시도, 우리는 종류의 결합 된 세트 [,]에서 선택한 후 우리는에 속하는 book_id 항목을 계산합니다 :

COUNT(IF(category_id = <given_category>, 1, NULL)) as cnt_exists 

를하고 필요한 범주에 포함되어 있음을 확인한 후 우리 지금은에 가지고 들어 ... 15초 PN 쿼리처럼 -

COUNT(*) AS cnt_total 


SELECT * FROM books b JOIN (
    SELECT book_id, 
     COUNT(IF(category_id = <given_category>, 1, NULL)) as cnt_exists, 
     COUNT(*) AS cnt_total FROM book_categories WHERE 
     category_id IN(<given_category>, <given_set_of_categories>) 
) bc ON b.id = bc.book_id AND 
     cnt_exists = 1 AND cnt_total = 1 ORDER BY b.inserted 
관련 문제