2009-03-23 9 views
4

Скажем, у меня есть таблица «Заказы», ​​созданные как:группы по вопросу в PostgreSQL

CREATE TABLE orders (id SERIAL, 
        customerID INTEGER, 
        timestamp BIGINT, 
        PRIMARY KEY(id)); 

Отметка является UNIX метка времени. Теперь я хочу выбрать идентификаторы LATEST заказов для каждого клиента. Как было бы хорошо.

Однако следующее утверждение

CREATE VIEW lastOrders AS SELECT id, 
            customerID, 
            MAX(timestamp) 
            FROM orders 
            GROUP BY customerID; 

Вызывает ошибку Postgre:

ERROR: column "orders.id" must appear in the GROUP BY clause or be used in an aggregate function

Что я делаю неправильно?

ответ

12

Для таких вещей вы можете использовать 2 подхода. Дженс уже показал.

Другое, является использование «DISTINCT ON» пункта:

CREATE VIEW lastOrders AS 
SELECT 
DISTINCT ON (customerID) 
    id, 
    customerID, 
    timestamp 
FROM orders 
ORDER BY customerID, timestamp desc; 
+0

посмотрел DISTINCT ON в postgres doc. Только то, что мне было нужно. Очень элегантно. Благодаря! – user54579

+0

Согласен. Это то, что приходит время от времени, и разработчики Postgres нашли хороший способ справиться с этим. Позор, это не часть стандартного SQL. – yukondude

0

Ответы kquinns исправит исключение, но это не то, что вы ищете.

Я не знаю особенности MySQL, но что-то, как это будет работать с оракулом:

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 

фактически с оракулом можно использовать аналитические функции, но я не думаю, что они доступны в MySQL

+0

Только для информации: плакат упоминается в postgresql. – ChristopheD

+0

Два опечатка: вы пропустите «AS» между max (timestamp) и timestamp, а a.customer_id следует заменить на a.customerID. – bortzmeyer

2

Следующий запрос должен возвращать только самый последний заказ для каждого клиента.

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 
     ); 

(Предполагая, что вы не можете иметь два заказа для клиента с точно таким же значением метки времени.)

Edit: Postgres-х DISTINCT ON гораздо niftier способ сделать это. Я рад, что узнал об этом. Но, вышеупомянутое работает для других РСУБД.

+0

Да, Jens Schauder и решения depesz тоже правильны. – bortzmeyer

+0

Вы правы. Другие правильны. – yukondude