[ANSWERED] Customer must own all 3 products

Hello,

I’m looking for a query that select all clientIDs that have ordered for example all 3 products.

Products: Table products
ID
Name

Order Table orders
ID
clientID
address etc.

Order Lines (products in order) orders_lines
orderID
productID

Clients table clients
ID
Name
Etc.

Now let’s say I want to select the clients that have ordered these 3 product:
1: Flowers
23: Sheep
163: Marbles
What query do I use to select all clients that have ALL of these product in the orders_lines table?

Help is much appreciated! :smile:

You would need to do three separate sub selects and join them in

SELECT C.Name
  FROM Client C
  JOIN (SELECT O.ClientID
	  FROM Orders O 
	  JOIN Order_Lines L ON O.ID = L.OrderID
	  JOIN Products P ON P.ID = L.ProductID
	 WHERE P.Name = 'Flowers') F ON F.ClientID = C.ClientID
  JOIN (SELECT O.ClientID
	  FROM Orders O 
	  JOIN Order_Lines L ON O.ID = L.OrderID
	  JOIN Products P ON P.ID = L.ProductID
	 WHERE P.Name = 'Sheep') S ON S.ClientID = C.ClientID
  JOIN (SELECT O.ClientID
	  FROM Orders O 
	  JOIN Order_Lines L ON O.ID = L.OrderID
	  JOIN Products P ON P.ID = L.ProductID
	 WHERE P.Name = 'Marbles') M ON M.ClientID = C.ClientID

This isn’t it I’m afraid, although I’m not sure what is, this doesn’t give me all clientIDs and selecting by name in a WHERE clause is obviously not the way to go.

This query selects all clients that have bought ANY of these three products.

SELECT `clientID` FROM
`orders_lines` INNER JOIN
`orders` ON
`orderID` = orders.ID
WHERE
`productID` IN (1,23,163)
GROUP BY clientID;

Now I need to get all clients that own ALL products.

It is just a matter of interpretation.

What @davemaxwell did was to get the list of clients that bought those three items (AND instead of OR).

Your query is fine. There is more than one way to do it

To get all clients than own ALL products, @davemaxwell’s query would be good… if you have a limited number of products, of course

OK, short of typos, what I gave you worked EXACTLY as you asked. It provided any client who ordered all three products, either in one order or over multiple orders.

Note: You need to add DISTINCT to the select to get rid of duplicates.

Are you sure your data matches what you’re expecting?

Why not? What’s the point of having the value table then?

The trick is using where with having to match only clients with the given number of products. In this case 3.

SELECT
     o.clientID
  FROM
     orders o
 INNER
  JOIN
     orders_lines i
    ON
     o.ID = i.orderID
 WHERE
     i.productID IN (1,23,163)
 GROUP
    BY
     o.clientID
HAVING
     COUNT(DISTINCT i.productID) = 3
1 Like

May I ask why shortening all those table names is so common? It’s just a sidequestion but it makes it unnecesary difficult to clearly read the query in my opinion.

Oddz, i like your query though! Let me test that.

Oh and you don’t select by productname because you have an ID to work with? It was just asample table structure.

It’s shorthand. You can use Products. instead of P. so it’s a matter of preference. I prefer the shorter version as I find it easier to read, especially if you’re working over multiple databases and multiple schemas.

Giving aliases help you to write faster, especially when you use a black screen which is quite common for most databases.

Thank you oddz! You just made my day with your super easy to understand query which works like a charm! Kudos!

a clear sign of an inefficient, clumsy query – it may produce the right results with DISTINCT added, but it stinks, no offence

@oddz beat me to it, the better query is GROUP BY HAVING COUNT(*)=3

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.