从连接表中返回单行>子表中有1行

时间:2012-07-01 16:38:54

标签: sql-server tsql

我有几张表books, bookcategories, categories

bookcategories是一个联接表,允许bookscategories之间的多对多关系。

我希望能够在书籍上运行类别搜索,这样即使书籍有很多类别,搜索也会为每本书返回一行。

图书

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

分类

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

BookCategories

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

我以为我可以逃脱这个:

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

但是只要我添加AND,查询就不会返回任何行。但这是我需要申请的标准 - 我只想返回书籍行,其中书籍同时具有上述类别1和2(即不属于类别1或类别2)

不禁想到我遗漏了一些非常基本的东西。有人可以帮忙吗?

我是否需要更改表格的结构,或者是否有办法实现我的需要。

3 个答案:

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

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

答案 2 :(得分:-1)

尝试添加select distinct并将and更改为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

distinct关键字不会返回重复的行;所以你现在可以使用categoryID = 1 OR categoryID = 2