2014-01-24 25 views
1

考虑数据库有这三个表获取客户,已下令两个特定的书籍从数据库中

BOOKID,ISBN,标题,URL,...)

客户客户ID,姓名,电子邮件,电话)

订购BOOKID客户ID,数量,日期)

我想要做的是,让谁下令两个特定图书的客户名为"BOOK A""BOOK B"

我想出了这样的查询:

SELECT o.customerId 
FROM Book b, Order o 
WHERE o.bookId = b.bookId 
AND b.title in ("BOOK A", "BOOK B"); 

导致谁下令至少一个的两本书我已指定客户。

任何帮助表示赞赏。

回答

2
SELECT o.customerId 
FROM Order o 
WHERE (SELECT count(distinct b.bookId) 
     FROM Book b 
     WHERE o.bookId = b.bookId 
     AND b.title in ('BOOK A', 'BOOK B') 
    ) = 2; 

这实质上将检查的每一订单的书的数量,限制在 “BOOK A” 和 “书B” 为2,也就是即两本书必须以相同的顺序

如果你想寻找的书籍在同一客户的任何命令,你需要的order的第二个实例:

SELECT o.customerId 
FROM Order o 
WHERE (SELECT count(distinct b.bookId) 
     FROM Book b JOIN Order oo ON oo.bookId = b.bookId 
     WHERE o.customerId = oo.customerId 
     AND b.title in ('BOOK A', 'BOOK B') 
    ) = 2; 

这可以优化,假设表Customer

SELECT c.customerId 
FROM Customer c 
WHERE (SELECT count(distinct b.bookId) 
     FROM Book b JOIN Order oo ON oo.bookId = b.bookId 
     WHERE c.customerId = oo.customerId 
     AND b.title in ('BOOK A', 'BOOK B') 
    ) = 2; 

这样可以避免结果中出现重复的客户,并加入更小的表格,因此应该更快。

所有这三种解决方案都可以轻松扩展到三,四本...书籍。只需在IN中列举它们并调整计数。

+2

这将返回客户ID,如果他们订购了Book A – Ghost

+0

@Ghost的两份副本,我纠正了这一点,计算不同的'bookId'秒。 – FrankPl

2
SELECT o.customerId 
FROM Book b, Order o 
WHERE o.bookId = b.bookId 
AND b.title in ("BOOK A") 
AND EXISTS (select 1 from Book bb, Order oo 
      where oo.bookId = bb.bookId 
      and oo.customerId = o.customerId 
      and bb.title in ("BOOK B")) 
+0

谢谢你的回答,它的工作原理。我不知道有什么办法可以做到这一点,而不使用'EXISTS'? –

+0

是的,用'1 ='0123'替换'存在'' – alfasin

+0

@alfasin如果图书被多次订购,那么用'1 ='替换'exists'将会失败,因为那么子查询会返回多行! – FrankPl