从一个类别中选择所有书籍,但属于其他类别的书籍除外

时间:2012-11-16 00:22:08

标签: mysql sql

我有3张桌子:booksbook_categoriescategories

book_categories表“加入”bookscategories。它包含以下列:idbook_idcategory_id

因此,一本书可能属于许多类别,而一个分类可能有很多书。

我需要查询从given_category检索所有图书,但属于given_set_of_categories的图书除外。因此,例如,我想要所有A类书籍,但前提是它们也不属于B类或C类。我还需要按Book.inserted列排序(排序)结果。

我知道如何从given_category获取所有包含2个联接的书籍,但无法弄清楚如何从结果中排除其他类别的某些书籍。我无法用PHP过滤书籍,因为我正在对搜索结果进行分页。

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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')

答案 2 :(得分:0)

我认为只要book_categories条目唯一,这可以通过计数来实现,因此组合book_id&amp; category_id 不重复。我们不是直接尝试排除记录,而是从组合的类别[,]中进行选择,然后我们将计算属于以下内容的book_id条目:

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

在确保其中包含所需类别后,我们会计算总数,以确定它是否属于任何其他类别:

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