Reputation: 50110
Imagine I have a product table and an orders table. I want to list out the most recent order for each product
I imagine something like this
select name, description, price, max(date)
from product
join order on order.item = product.name
group by order.item
But my postgres DB complains that I cant have raw fields (sqlite doesnt complain) I need to have aggregate function. I can put min() for each column but that seems like a waste, given that all the values for a particular product are always the same. I wondered about 'distinct' but that doesnt seem to help here
NOTE - I need standard portable SQL , not specific to any given engine.
Upvotes: 1
Views: 803
Reputation: 50163
You can use correlated subquery :
select p.name, p.description, p.price, o.date
from product p inner join
order o
on o.item = p.name
where o.date = (select max(o1.date)
from order o1
where o1.item = p.name
);
Upvotes: 0
Reputation: 167
If it was Oracle or MS you would need to group by all the fields in your select that aren't aggregate functions. It would be an extra line before "order by" with "group by p.name, description, price, date" ... About Postgres I am not so sure, but probably it will work.
Upvotes: 0
Reputation:
If you require standard ANSI SQL you can use a window function:
select *
from (
select p.name, p.description, p.price,
o.date,
max(o.date) over (partition by o.item) as last_date
from product p
join "order" o on o.item = p.name
) t
where date = last_date;
But in Postgres distinct on ()
is usually a lot faster.
Upvotes: 1
Reputation: 1269493
In Postgres, you can use distinct on
:
select distinct on (o.item) p.name, description, price, date
from product p join
order o
on o.item = p.name
order by o.item, date desc;
I added aliases into the query. I strongly advise you to always qualify all column names. I would do that but I don't know where they come from in most cases.
Upvotes: 1