选择所有客户,除非他们有其他产品 - SQL

时间:2016-03-29 19:07:58

标签: mysql sql

我有两张桌子。一个由客户组成,另一个由他们购买的产品组成:

表客户

CustID, Name
  1,     Tom 
  2,     Lisa 
  3,     Fred

表产品

CustID, Item
  1,     Toaster
  1,     Breadbox
  2,     Toaster
  3,     Toaster

我想让所有购买烤面包机的顾客,除非他们还买了面包箱。

所以我尝试了以下内容:

SELECT * FROM Customer
JOIN Product
    ON Customer.CustID=Product.CustID
WHERE Product in
    (SELECT 
        Item
    FROM Product
    WHERE (Item = 'Toaster' AND Item != 'Breadbox'));

SELECT * FROM Customer
INNER Join Product
ON Customer.CustID=PRODUCT.CustID
WHERE Product.Item = 'Toaster'
AND Product.Item NOT IN ('Breadbox');

但两者都给出了相同的结果,其中包括已经拥有面包箱的汤姆。

如何确保只有拥有烤面包机但没有面包箱的客户才能上市?

5 个答案:

答案 0 :(得分:2)

SELECT * FROM Customer C
LEFT JOIN Product PT ON C.CustID = PT.CustID AND PT.Item = 'Toaster'
LEFT JOIN Product PB ON C.CustID = PB.CustID AND PB.Item = 'Breadbox'
WHERE PT.Item IS NOT NULL AND PB.Item IS NULL

答案 1 :(得分:2)

这是我的第一篇文章,原谅任何失误。 Customer和Product表之间存在“多对一”关系。要制定要应用的逻辑限制,您需要聚合Product表或连接Product表两次。实际上,你正在寻求将多对一关系折叠成“一对一”的关系。

以下是Product表连接两次的一些示例。

SELECT DISTINCT
a.Name
FROM
Customer a
JOIN Product b ON a.CustID = b.CustID
LEFT JOIN Product c on a.CustID = c.CustID AND c.Item = 'Breadbox'
WHERE
b.Item = 'Toaster' AND
c.CustID IS NULL

或(根据索引效率略低)

SELECT DISTINCT
a.Name
FROM
Customer a
JOIN Product b ON a.CustID = b.CustID
WHERE
b.Item = 'Toaster' AND
NOT EXISTS (SELECT 1 FROM Product c where a.CustID = c.CustID AND c.Item = 'Breadbox')

并且,以下是Product表连接一次的示例 - 可能比您需要的更复杂。

SELECT
a.Name
FROM
Customer a
JOIN
(
    SELECT 
    CustID, 
    SUM(case when Item = 'Toaster' then 1 else 0 end) sum_Toaster,
    SUM(case when Item = 'Breadbox' then 1 else 0 end) sum_Breadbox
    FROM
    Product
    WHERE 
    Item in ('Toaster','Breadbox')
    GROUP BY
    CustID
    HAVING
    SUM(case when Item = 'Toaster' then 1 else 0 end) > 0 AND
    SUM(case when Item = 'Breadbox' then 1 else 0 end) = 0
) b ON a.CustID = b.CustID

答案 2 :(得分:1)

试试这个:

SELECT c.CustID, c.Name
FROM customer AS c
JOIN product AS p ON c.CustID = p.CustID
GROUP BY c.CustID, c.Name
HAVING SUM(p.Item = 'Toaster') >= 1 AND SUM(p.Item = 'Breadbox') = 0

答案 3 :(得分:1)

SELECT distinct * FROM Customer
 LEFT JOIN Product ON Customer.CustID=Product.CustID
WHERE Item = 'Toaster'
AND Customer.CustID NOT IN (
Select CustID FROM Product Where Item = 'Breadbox'
)

答案 4 :(得分:0)

having
        count(case when p.Item = 'Toaster'  then 1 end) > 0
    and count(case when p.Item = 'Breadbox' then 1 end) = 0

where

对于第二种情况,您并不严格需要{{1}},尽管它可能有助于在大型表上执行。