grupo por la pregunta en PostgreSQL
-
21-08-2019 - |
Pregunta
Decir que tengo una mesa de 'órdenes' creados como:
CREATE TABLE orders (id SERIAL,
customerID INTEGER,
timestamp BIGINT,
PRIMARY KEY(id));
Fecha y hora siendo la marca de tiempo UNIX. Ahora quiero para seleccionar los identificadores de las órdenes más reciente para cada cliente. Como una vista estaría bien.
Sin embargo, la siguiente declaración
CREATE VIEW lastOrders AS SELECT id,
customerID,
MAX(timestamp)
FROM orders
GROUP BY customerID;
provoca un error de PostgreSQL:
ERROR: columna "orders.id" debe aparecer en el GROUP BY cláusula o ser usado en una función de agregado
¿Qué estoy haciendo mal?
Solución
Para este tipo de cosas que se pueden utilizar 2 enfoques. Uno ha sido ya demostrado por Jens.
Otro, es el uso de "DISTINCT ON" cláusula:
CREATE VIEW lastOrders AS
SELECT
DISTINCT ON (customerID)
id,
customerID,
timestamp
FROM orders
ORDER BY customerID, timestamp desc;
Otros consejos
La siguiente consulta debería devolver sólo el último fin de que cada cliente.
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
);
(Suponiendo que no se puede tener dos pedidos de un cliente con el mismo valor de marca de tiempo.)
Editar: DISTINCT ON
de Postgres es una manera mucho niftier de hacer esto. Estoy contento de haber aprendido de él. Sin embargo, lo anterior funciona para otros RDBMS.
kquinns respuesta va a fijar la excepción, pero no es lo que busca.
No sé las características de MySQL, pero algo como esto iba a trabajar con 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
realidad con Oracle se podría utilizar las funciones analíticas, pero no creo que están disponibles en MySQL