Reputation: 8580
Consider the following scenario :
an Item has a Price
a Order contains Items
a Delivery contains Orders
I want to query for each delivery, the order with the highest price, where a price of an order is the summation of prices of the contained items.
A simple sufficient schema would look like this :
Delivery
d_id
Order
o_id
Item
i_id,price
ItemsInOrder
o_id,i_id
OrdersInDelivery
d_id,o_id
I am stuck in the point of having the summation results, needing to get the max order per delivery :
SELECT d_id,o_id,SUM(price)
from ItemsInOrder
natural join OrdersInDelivery
natural join Item
group by d_id,o_id
How should i go from here to get that each d_id, would appear once and aside the o_id with the maximal price summation?
Upvotes: 2
Views: 119
Reputation: 8580
Thanks for all your answers, but none of them was what i was looking for. I finally found what i was looking for and the approach i choose is as follows :
SELECT d_id,o_id,sum_price
FROM (
SELECT d_id,o_id,SUM(price) as sum_price
from ItemsInOrder
natural join OrdersInDelivery
natural join Item
group by d_id,o_id
order by d_id,sum_price desc
) as sums
GROUP BY d_id
Upvotes: 1
Reputation: 9578
You can use Left Joining with self, tweaking join conditions and filters. In this approach, you left join the table with itself. Equality, of course, goes in the group-identifier.
SELECT a.*
FROM (
SELECT oid.d_id AS d_id, o_id, SUM(price) AS sum_price
FROM `OrdersInDelivery` oid
INNER JOIN `ItemsInOrder` iio USING (o_id)
INNER JOIN `Item` i USING (i_id)
GROUP BY d_id, o_id
) a
LEFT OUTER JOIN (
SELECT oid.d_id AS d_id, o_id, SUM(price) AS sum_price
FROM `OrdersInDelivery` oid
INNER JOIN `ItemsInOrder` iio USING (o_id)
INNER JOIN `Item` i USING (i_id)
GROUP BY d_id, o_id
)b
ON a.d_id = b.d_id AND a.sum_price < b.sum_price
WHERE b.d_id IS NULL AND b.o_id IS NULL;
Take a look at this query in SQL fiddle: http://sqlfiddle.com/#!9/d5c04d/1
In that case it's recommended to use TEMPORARY TABLE
:
CREATE TEMPORARY TABLE OrderSummary(
SELECT oid.d_id AS d_id, o_id, SUM(price) AS sum_price
FROM `OrdersInDelivery` oid
INNER JOIN `ItemsInOrder` iio USING (o_id)
INNER JOIN `Item` i USING (i_id)
GROUP BY d_id, o_id
);
CREATE TEMPORARY TABLE OrderSummary2(
SELECT * FROM OrderSummary
);
SELECT a.*
FROM OrderSummary a
LEFT OUTER JOIN OrderSummary2 b
ON a.d_id = b.d_id AND a.sum_price < b.sum_price
WHERE b.d_id IS NULL AND b.o_id IS NULL;
Upvotes: 1
Reputation: 263
I'm sharing the results that I've got so far so anyone could continue to help you because i need to leave to airport now :) I'll try to check it again tomorrow if no one figure it out.
its a challenging question guys.
I have already prepared some samples here : http://sqlfiddle.com/#!9/d4fed2
And the latest query i did is :
SELECT d_id,OID.o_id,sumPrice
from OrdersInDelivery OID
join (SELECT IIO.o_id,SUM(I.price) as sumPrice
from ItemsInOrder IIO
join item I on I.i_id = IIO.i_id
group by IIO.o_id) IIO1 on OID.o_id = IIO1.o_id
Good luck :)
Upvotes: 0
Reputation: 1269933
Don't use natural join
. They are an error waiting to happen, because they depend on the names of columns in the tables -- not even using properly and explicitly defined foreign key relationships. Use on
or using
instead.
This type of query is painful in MySQL, because MySQL does not support CTEs (common table expressions) nor does it support window functions. So, the query is more complicated than in other databases:
select oid.d_id, o_id, SUM(price)
from OrdersInDelivery oid join
ItemsInOrder iio
using (o_id)
Item i
using (i_id)
group by d_id, o_id
having sum(price) = (select sum(iio2.price)
from ItemsInOrder iio2 join
Item i2
using (i_id)
where iio2.d_id = iio.d_id
group by iio2.o_id
order by sum(iio2.price) desc
limit 1
);
Upvotes: 0