Reputation: 262
I have two tables that I need to combine to get the data I need, but the queries that give the desired result are all very expensive.
I have a products table (id, name) and a stock table (id, pid, supplier, stock, price). The stock.pid is the foreign key to products.id, but each product can have multiple suppliers and therefor multiple entries in the stock table.
What I need is for each product the cheapest price and current stock, combined with all data from the products record, ordered on prices ascending.
What I tried is (and several variations):
SELECT DISTINCT(pid), MIN(price), stock, p.*
FROM stock s LEFT (INNER) JOIN
product
ON pid = s.id
GROUP BY pid
ORDER BY price (LIMIT 100)
Upvotes: 0
Views: 116
Reputation: 262
I've solved the problem as follows, also adding an extra level where the current time is taken into account because some suppliers cannot deliver on time after a certain time of day. What I did not include is a sum(stock). I've added that field to the products table as sumStock and always update it whenever a stock record is changed.
SELECT sp.price
, p.*
FROM products p
LEFT JOIN stock_products sp
USING (ean)
WHERE sp.id = IFNULL(
(SELECT psi.id
FROM stock_products psi
JOIN suppliers sup
ON psi.pid = sup.id
WHERE psi.ean = p.ean
AND psi.stock > 0
ORDER BY IF(sup.time>40667, sup.deliveryTime, sup.deliveryTime+86400)
, price
LIMIT 1)
,
(SELECT psi.id
FROM stock_products psi
JOIN suppliers sup
ON psi.pid = sup.id
WHERE psi.ean = p.ean
ORDER BY IF(sup.time>40667, sup.deliveryTime, sup.deliveryTime+86400)
, price
LIMIT 1)
ORDER BY price
Note that I use the IFNULL for the rare cases a product has no stock. I still want to show those records. The query is a bit shorter without, but this is the complete solution I ended up using.
Also, 40667 is a number representing the current time. It should be whatever the current number of seconds since midnight is.
Upvotes: 0
Reputation: 20330
Um
Select products.*,stock.stock,cheapest.cheapestprice
From (select id,Min(Price) as cheapestPrice From Stock Group By id) cheapest
inner join Stock on stock.id = cheapest.id
inner join products on product.id = stock.pid
Order by cheapest.cheapestprice
maybe
Upvotes: 1
Reputation: 1271003
You want to do this with a subquery:
select p.*, sumstock, minprice
from products p left outer join
(select s.pid, sum(stock) as sumstock, min(price) as minprice
from stock s
group by s.pid
) sp
on sp.pid = p.id
order by minprice
Upvotes: 0