SQL Fiddle:
CREATE TABLE Purchasing (
Event_Type VARCHAR(255),
Campaign VARCHAR(255),
Quantity_Offer VARCHAR(255),
Quantity_
SELECT x.campaign
, COALESCE(z.event_type,y.event_type,x.event_type) event_type
, COALESCE(z.quantity_received,y.quantity_order,x.quantity_offer) quantity
FROM purchasing x
LEFT
JOIN purchasing y
ON y.campaign = x.campaign
AND y.event_type = 'order'
LEFT
JOIN purchasing z
ON z.campaign = y.campaign
AND z.event_type = 'received'
WHERE x.event_type = 'offer'
http://www.sqlfiddle.com/#!9/2b9394/37
Use this for your query.
this is based you first make your offer, then comes tghe order and at last comes the received, when 1 of them in that order is empty, then 1 prior must be the current state.
SELECT
Campaign,
IF(QReceived IS NOT NULL, "Received",
IF(QOrder IS NOT NULL, "Order",
IF(QOffer IS NOT NULL, "Offer", NULL))) Event_Type,
IF(QReceived IS NOT NULL, QReceived,
IF(QOrder IS NOT NULL, QOrder,
IF(QOffer IS NOT NULL, QOffer, NULL))) qty
FROM
(SELECT
Campaign,
SUM(Quantity_Received) QReceived,
SUM(Quantity_Order) QOrder,
SUM(Quantity_Offer) QOffer
FROm Purchasing
GROUP BY Campaign) t1
Which gives you foolowing result
Campaign Event_Type qty
C001 Received 310
C002 Received 190
C003 Order 450
C004 Order 630
C005 Offer 400
C006 Offer 300
http://www.sqlfiddle.com/#!9/2b9394/34
This is a prioritization query.
In MySQL 8+, use window functions:
select campaign, event_type,
coalesce(Quantity_Offer, Quantity_Order, Quantity_Received) as quantity
from (select p.*,
row_number() over (partition by campaign order by field(event_type, 'Received', 'Order', 'Offer')) as seqnum
from Purchasing p
) p
where seqnum = 1;
In earlier versions, a simple method is a correlated subquery:
select campaign, event_type,
coalesce(Quantity_Offer, Quantity_Order, Quantity_Received) as quantity
from Purchasing p
where event_type = (select p2.event_type
from Purchasing p2
where p2.campaign = p.campaign
order by field(p2.event_type, 'Received', 'Order', 'Offer')
limit 1
);
If you have a lot of data, you want an index on Purcahsing(campaign, event_type)
for this query.
Here is a db<>fiddle.
Since by string comparison 'Offer' < 'Order' < 'Received'
, you can use the classic way with a group by subquery, to find the "latest" row:
select
p.Campaign,
p.Event_Type,
case p.Event_Type
when 'Order' then p.Quantity_Order
when 'Offer' then p.Quantity_Offer
when 'Received' then p.Quantity_Received
end as Quantity
from (
select Campaign, max(Event_Type) as Event_Type
from Purchasing
group by Campaign
) mx
natural join Purchasing p
order by p.Campaign
Result:
| Campaign | Event_Type | Quantity |
| -------- | ---------- | -------- |
| C001 | Received | 310 |
| C002 | Received | 190 |
| C003 | Order | 450 |
| C004 | Order | 630 |
| C005 | Offer | 400 |
| C006 | Offer | 300 |
View on DB Fiddle
But if you were not so lucky with your Event_Type
values, or if you want a more solid (more reliable) solution, you would need to define a custom order with either FIELD()
, FIND_IN_SET()
, a case statement, or a sort mapping (derived) table. Here a way using FIELD()
:
select
p.Campaign,
p.Event_Type,
case p.Event_Type
when 'Order' then p.Quantity_Order
when 'Offer' then p.Quantity_Offer
when 'Received' then p.Quantity_Received
end as Quantity
from Purchasing p
where p.Event_Type = (
select p1.Event_Type
from Purchasing p1
where p1.Campaign = p.Campaign
order by field(p1.Event_Type, 'Offer', 'Order', 'Received') desc
limit 1
)
order by p.Campaign
View on DB Fiddle