Reputation: 4688
Say I have a table 'orders' created as:
CREATE TABLE orders (id SERIAL,
customerID INTEGER,
timestamp BIGINT,
PRIMARY KEY(id));
Timestamp being the UNIX timestamp. Now i want to select the ids of the LATEST orders for every customer. As a view would be nice.
however the following statement
CREATE VIEW lastOrders AS SELECT id,
customerID,
MAX(timestamp)
FROM orders
GROUP BY customerID;
Causes a postgre error:
ERROR: column "orders.id" must appear in the GROUP BY clause or be used in an aggregate function
What am I doing wrong?
Upvotes: 4
Views: 4650
Reputation: 24683
The following query should return only the very last order for each customer.
CREATE VIEW last_orders AS
SELECT id, customer_id, timestamp
FROM orders AS o
WHERE timestamp = (
SELECT MAX(timestamp)
FROM orders AS oi
WHERE o.customer_id = oi.customer_id
);
(Assuming that you can't have two orders for a customer with the exact same timestamp value.)
Edit: Postgres's DISTINCT ON
is a much niftier way of doing this. I'm glad I learned about it. But, the above works for other RDBMSs.
Upvotes: 2
Reputation:
For these kind of things you can use 2 approaches. One has been already shown by Jens.
Other, is to use "DISTINCT ON" clause:
CREATE VIEW lastOrders AS
SELECT
DISTINCT ON (customerID)
id,
customerID,
timestamp
FROM orders
ORDER BY customerID, timestamp desc;
Upvotes: 12
Reputation: 81988
kquinns answer will fix the exception, but isn't what you are looking for.
I don't know the features of mysql but something like this would work with oracle:
select a.*
from
orders a,
(select customerID, max(timestamp) timestamp
from orders group by customerID
) b
where a.customer_id = b.customerID
and a.timestamp = b.timestamp
actually with oracle one could use analytic functions, but I do not think they are available in mysql
Upvotes: 0