Este es un obstáculo clásico con el que se topan la mayoría de los programadores de MySQL.
- Tienes una columna
ticket_id
ese es el argumento paraGROUP BY
. Valores distintos en esta columna definen los grupos. - Tiene una columna
incoming_time
ese es el argumento deMAX()
. El mayor valor de esta columna sobre las filas de cada grupo se devuelve como el valor deMAX()
. - Tienes todas las demás columnas del artículo de la tabla. Los valores devueltos para estas columnas son arbitrarios, no de la misma fila donde
MAX()
se produce el valor.
La base de datos no puede inferir que desea valores de la misma fila donde se encuentra el valor máximo.
Piensa en los siguientes casos:
-
Hay varias filas donde se produce el mismo valor máximo. Qué fila debe usarse para mostrar las columnas de
article.*
? -
Escribes una consulta que devuelve tanto el
MIN()
y elMAX()
. Esto es legal, pero qué fila debearticle.*
mostrar?SELECT article.* , MIN(article.incoming_time), MAX(article.incoming_time) FROM ticket, article WHERE ticket.id = article.ticket_id AND ticket.queue_id = 1 GROUP BY article.ticket_id
-
Utiliza una función agregada como
AVG()
oSUM()
, donde ninguna fila tiene ese valor. ¿Cómo adivina la base de datos qué fila mostrar?SELECT article.* , AVG(article.incoming_time) FROM ticket, article WHERE ticket.id = article.ticket_id AND ticket.queue_id = 1 GROUP BY article.ticket_id
En la mayoría de las marcas de bases de datos, así como en el propio estándar SQL, no está permitido para escribir una consulta como esta, debido a la ambigüedad. No puede incluir ninguna columna en la lista de selección que no esté dentro de una función agregada o nombrada en GROUP BY
cláusula.
MySQL es más permisivo. Le permite hacer esto y le deja a usted escribir consultas sin ambigüedad. Si tiene ambigüedad, selecciona valores de la fila que está físicamente primero en el grupo (pero esto depende del motor de almacenamiento).
Por lo que vale, SQLite también tiene este comportamiento, pero elige el último fila en el grupo para resolver la ambigüedad. Imagínate. Si el estándar SQL no dice qué hacer, depende de la implementación del proveedor.
Aquí hay una consulta que puede resolver su problema por usted:
SELECT a1.* , a1.incoming_time AS maxtime
FROM ticket t JOIN article a1 ON (t.id = a1.ticket_id)
LEFT OUTER JOIN article a2 ON (t.id = a2.ticket_id
AND a1.incoming_time < a2.incoming_time)
WHERE t.queue_id = 1
AND a2.ticket_id IS NULL;
En otras palabras, busca una fila (a1
) para el que no hay otra fila (a2
) con el mismo ticket_id
y un mayor incoming_time
. Si no hay mayor incoming_time
se encuentra, LEFT OUTER JOIN devuelve NULL en lugar de una coincidencia.