1

I have several tables, books, bookcategories, categories

bookcategories is a join table to allow the many to many relationship between books and categories.

I want to be able to run a category search on books such that the search returns one row per book even when the book has many categories.

Books

ID   | Title
1    | Once upon...
2    | How many...
3    | How much...

Categories

ID   | Category
1    | x
2    | y
3    | z

BookCategories

   BookId | CategoryId
     1    |     1
     1    |     2
     2    |     2
     2    |     3
     2    |     1
     3    |     1

I thought I could get away with this:

SELECT  b.Id,
    b.Title,
FROM    ( books b
    INNER JOIN bookcategories bc ON b.ID= bc.BookId
    )
WHERE (bc.categoryId =1 AND bc.categoryId=2)
GROUP BY b.Id, b.Title

but as soon as I add the AND, the query returns no rows. But that is the criteria I need to apply - I only want to return book rows where the book has both category 1 and 2 as above (i.e. not category 1 OR category 2)

Can't help thinking that I am missing something quite basic. Can anyone help?

Do I need to change the structure of the tables or is there a way of achieving what I need.

Wing

4

3 回答 3

1

这应该返回同时具有第一类和第二类的书籍:

select  b.Id
,       b.Title
from    books b
join    bookcategories bc
on      bc.BookId = b.Id
group by
         b.Id
,        b.Title
having   sum(case when bc.categoryId = 1 then 1 end) > 0
         and sum(case when bc.categoryId = 2 then 1 end) > 0

或者,您可以使用双重exists子句:

select  b.Id
,       b.Title
from    books b
where   exists
        (
        select  *
        from    bookcategories bc
        where   bc.BookId = b.Id
                and bc.CategoryId = 1
        )
        and exists
        (
        select  *
        from    bookcategories bc
        where   bc.BookId = b.Id
                and bc.CategoryId = 2
        )
于 2012-07-01T16:44:43.307 回答
0

另一种选择(至少基于我认为你想要的):

SELECT ID, Title
FROM 
(
  SELECT b.ID, b.Title, c = COUNT(bc.BookID)
  FROM dbo.Books AS b
  INNER JOIN dbo.BookCategories AS bc
  ON b.ID = bc.BOokID
  AND bc.CategoryID IN (1,2)
  GROUP BY b.ID, b.Title
) AS x
WHERE c >= 2; -- in case there is no unique constraint on BookCategories

虽然这也应该有效:

SELECT b.ID, b.Title
  FROM dbo.Books AS b
  INNER JOIN dbo.BookCategories AS bc
  ON b.ID = bc.BOokID
  AND bc.CategoryID IN (1,2)
GROUP BY b.ID, b.Title
HAVING COUNT(*) >= 2;
于 2012-07-01T17:48:25.327 回答
-1

Try adding select distinct and changing the and to an or.

SELECT      DISTINCT b.Id, b.Title
FROM        books b
INNER JOIN  bookcategories bc ON b.ID= bc.BookId
WHERE       (bc.categoryId=1 OR bc.categoryId=2)
ORDER BY    b.ID

The distinct keyword will NOT return duplicate rows; so you can now use categoryID = 1 OR categoryID = 2.

于 2012-07-01T16:52:40.070 回答