Reputation: 71
I have this table of orders and statuses:
id | date | status
123 2015-12-01 order
123 2015-12-20 refund
234 2015-12-21 order
456 2015-12-22 order
456 2015-12-22 refund
Now I'd like to get results on 'status' column that whenever the ID also has a status of 'refund' then use this value instead of value 'order'.
As follows:
id | date | status | refund_date
123 2015-12-01 refund 2015-12-20
234 2015-12-21 order
456 2015-12-22 refund 2015-12-22
I have this query that retrieves the refund_date but I'm unsure how to get the status for refund orders. Additionally the table has like 500k records so performance is a key.
select
id,
date,
status,
case when count(id)>1 then max(date) else min(date) end as refund_date
from orders
group by id
Much appreciated.
Upvotes: 0
Views: 1590
Reputation: 8204
Join an "order" view of the table with a "refund" view of the table. Use coalesce, which is a function that evaluates to the first non-null argument, to identify the status.
select t1.id, t1.date, coalesce(t2.status, t1.status), t2.date
from orders t1 left outer join t2 on (t1.id = t2.id and t2.status = 'refund')
where t1.status = 'order'
Upvotes: 0
Reputation: 1270713
One method is to use union all
for this purpose:
select o.*
from orders o
where o.status = 'refund'
union all
select o.*
from orders o
where o.status = 'order' and
not exists (select 1
from orders o2
where o2.id = o.id and o2.status = 'refund'
);
With indexes on orders(status)
and orders(id, status)
, this query should be quite fast.
Upvotes: 1