0

Newbie here using W3schools demo database to practice SQL queries and I'm stuck on one:

SELECT Customers.CustomerID, Customers.CustomerName, Orders.OrderID, OrderDetails.ProductID, Products.ProductName FROM Customers
INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID
INNER JOIN OrderDetails ON OrderDetails.OrderID = Orders.OrderID
INNER JOIN Products ON Products.ProductID = OrderDetails.ProductID
WHERE OrderDetails.ProductID <> 70

I want to see a list of customers who have made an order, but have not ordered product ID 70.

This query still shows the other orders of customer's who have ordered product ID 70. If a customer has ordered it, I don't want to see any of their other orders on this list. Does this scenario call for a subquery using WHERE EXISTS?

Thanks!

0

3 Answers 3

1

Use aggregation:

SELECT c.CustomerID, c.CustomerName
FROM Customers c JOIN
     Orders o
     ON c.CustomerID = o.CustomerID JOIN
     OrderDetails od
     ON od.OrderID = o.OrderID
GROUP BY c.CustomerID, c.CustomerName
HAVING SUM(CASE WHEN od.ProductID = 70 THEN 1 ELSE 0 END) = 0;

This is a different question from asking which orders have product 70. That question can be answered just by looking at a row to see if the product is there. However, to determine whether or not product 70 is in any order, you need to look at all of them, which is why aggregation is needed.

Sign up to request clarification or add additional context in comments.

Comments

1

It sounds like you're just looking for the NOT keyword:

SELECT Customers.CustomerID, Customers.CustomerName, Orders.OrderID, OrderDetails.ProductID, Products.ProductName FROM Customers
INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID
INNER JOIN OrderDetails ON OrderDetails.OrderID = Orders.OrderID
INNER JOIN Products ON Products.ProductID = OrderDetails.ProductID
WHERE NOT OrderDetails.ProductID = 70

2 Comments

NOT OrderDetails.ProductID = 70 is exactly the same thing as OrderDetails.ProductID <> 70
This yields the same result, which is not what I'm looking for.
1

You can indeed use an NOT EXSISTS query for that:

SELECT c.*
FROM customers c
WHERE NOT EXISTS (select *
                  from orders o
                    join orderdetails od on o.orderid = od.orderid
                  where o.customerid = c.customerid
                    and od.productid = 70);

The subquery tests if there is at least one order with productid = 70 for each customer. If no such order exists, NOT EXISTS will result in "true", thus including that customer in the overall result.

As you only want the list of customers, there is no need to join in the orders table into the main query.

1 Comment

Thanks, this works too, but it shows all customers including ones that have not ordered anything. I edited my question to further clarify that the query is for customers who have made an order.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.