Este é um obstáculo clássico que a maioria dos programadores MySQL encontra.
- Você tem uma coluna
ticket_id
esse é o argumento paraGROUP BY
. Valores distintos nesta coluna definem os grupos. - Você tem uma coluna
incoming_time
esse é o argumento paraMAX()
. O maior valor nesta coluna sobre as linhas em cada grupo é retornado como o valor deMAX()
. - Você tem todas as outras colunas do artigo da tabela. Os valores retornados para essas colunas são arbitrários, não da mesma linha em que
MAX()
valor ocorre.
O banco de dados não pode inferir que você deseja valores da mesma linha em que ocorre o valor máximo.
Pense nos seguintes casos:
-
Existem várias linhas em que ocorre o mesmo valor máximo. Qual linha deve ser usada para mostrar as colunas dearticle.*
?
-
Você escreve uma consulta que retorna tanto oMIN()
e oMAX()
. Isso é legal, mas qual linha devearticle.*
exposição?
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
-
Você usa uma função agregada comoAVG()
ouSUM()
, onde nenhuma linha tem esse valor. Como o banco de dados adivinha qual linha exibir?
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
Na maioria das marcas de banco de dados -- assim como no próprio padrão SQL -- você não tem permissão escrever uma consulta como esta, por causa da ambiguidade. Você não pode incluir nenhuma coluna na lista de seleção que não esteja dentro de uma função agregada ou nomeada no
GROUP BY
cláusula. MySQL é mais permissivo. Ele permite que você faça isso e deixa para você escrever consultas sem ambiguidade. Se você tiver ambiguidade, ele selecionará valores da linha que está fisicamente primeiro no grupo (mas isso depende do mecanismo de armazenamento).
Vale a pena, o SQLite também tem esse comportamento, mas escolhe o último linha no grupo para resolver a ambiguidade. Vai saber. Se o padrão SQL não diz o que fazer, cabe à implementação do fornecedor.
Aqui está uma consulta que pode resolver seu problema para você:
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;
Em outras palavras, procure por uma linha (
a1
) para a qual não há outra linha (a2
) com o mesmo ticket_id
e um incoming_time
maior . Se não houver mais incoming_time
for encontrado, LEFT OUTER JOIN retornará NULL em vez de uma correspondência.