简体   繁体   中英

MYSQL: How to Select Customers That Bought One Product But Not Another

I am working on a database and I would like to get the list of all the customers that bought a product with a name containing citroen but none with a name containing guzzi.

The structure of the database is the following:

数据库

I have tried the following:

SELECT customerName, productName
FROM customers c
INNER JOIN orders o
USING (customerNumber)
INNER JOIN orderdetails od
USING (orderNumber)
INNER JOIN products p
USING (productCode)
WHERE productName LIKE '%citroen%'
AND productName NOT IN (
SELECT productCode
FROM products
WHERE productName LIKE '%guzzi%'
);

but it selects also the one who bought guzzi.

Any clue?

Conditional aggregation to count how many products of each type were purchased...

SELECT
  o.customerNumber
FROM
  orders o
INNER JOIN
  orderdetails od
    USING (orderNumber)
INNER JOIN
  products p
    USING (productCode)
WHERE
     p.productName LIKE '%citroen%'
  OR p.productName LIKE '%guzzi%'
GROUP BY
  o.customerNumber
HAVING
      MAX(CASE WHEN p.productName LIKE '%citroen%' THEN 1 ELSE 0 END) = 1
  AND MAX(CASE WHEN p.productName LIKE '%guzzi%'   THEN 1 ELSE 0 END) = 0

Longer, but can be faster if each customer has (on average) a very large number of relevant purchases...

SELECT
  *
FROM
  customer
WHERE
  EXISTS (
    SELECT
      o.customerNumber
    FROM
      orders o
    INNER JOIN
      orderdetails od
        USING (orderNumber)
    INNER JOIN
      products p
        USING (productCode)
    WHERE
          o.customerNumber  =   customer.CustomerNumber
      AND p.productName    LIKE '%citroen%'
  )
  AND NOT EXISTS (
    SELECT
      o.customerNumber
    FROM
      orders o
    INNER JOIN
      orderdetails od
        USING (orderNumber)
    INNER JOIN
      products p
        USING (productCode)
    WHERE
          o.customerNumber  =   customer.CustomerNumber
      AND p.productName    LIKE '%guzzi%'
  )

In your last condition, you're comparing productName with productCode, so I suppose the NOT IN will always return TRUE.

SELECT customerName, productName
FROM customers c
    INNER JOIN orders o
        USING (customerNumber)
    INNER JOIN orderdetails od
        USING (orderNumber)
    INNER JOIN products p
        USING (productCode)
WHERE productName LIKE '%citroen%'
AND NOT EXISTS (
    SELECT 'x'
    FROM orders o2
        INNER JOIN orderdetails od2
            USING (orderNumber)
        INNER JOIN products p2
            USING (productCode)
    WHERE o2.customerNumber = c.customerNumber
    AND p2.productName LIKE '%guzzi%'
)
AND productName NOT LIKE '%guzzi%'
;```

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM