Quero poder selecionar um monte de linhas de uma tabela de e-mails e agrupá-las pelo remetente. Minha consulta é semelhante a esta:
SELECT
`timestamp`, `fromEmail`, `subject`
FROM `incomingEmails`
GROUP BY LOWER(`fromEmail`)
ORDER BY `timestamp` DESC
A consulta funciona quase como eu desejo - ela seleciona registros agrupados por e-mail. O problema é que o assunto e o carimbo de data / hora não correspondem ao registro mais recente de um endereço de e-mail específico.
Por exemplo, pode retornar:
fromEmail: john@example.com, subject: hello
fromEmail: mark@example.com, subject: welcome
Quando os registros no banco de dados são:
fromEmail: john@example.com, subject: hello
fromEmail: john@example.com, subject: programming question
fromEmail: mark@example.com, subject: welcome
Se o assunto "questão de programação" for o mais recente, como posso fazer com que o MySQL selecione esse registro ao agrupar os e-mails?
fonte
As of 5.7.5 ONLY_FULL_GROUP_BY is enabled by default, i.e. it's impossible to use non-aggregate columns.
O modo SQL pode ser alterado durante o tempo de execução sem privilégios de administrador, por isso é muito fácil desabilitar ONLY_FULL_GROUP_BY. Por exemplo:SET SESSION sql_mode = '';
. Demo: db-fiddle.com/f/esww483qFQXbXzJmkHZ8VT/3Aqui está uma abordagem:
Basicamente, você une a tabela a si mesma, procurando por linhas posteriores. Na cláusula where, você afirma que não pode haver linhas posteriores. Isso fornece apenas a linha mais recente.
Se houver vários e-mails com o mesmo carimbo de data / hora, essa consulta precisará ser refinada. Se houver uma coluna de ID incremental na tabela de e-mail, altere o JOIN como:
fonte
textID
era ambíguo = /LEFT JOIN
critériosAND next.timestamp <= UNIX_TIMESTAMP()
Como já apontado em uma resposta, a resposta atual está errada, pois o GROUP BY seleciona arbitrariamente o registro da janela.
Se alguém estiver usando o MySQL 5.6 ou MySQL 5.7 com
ONLY_FULL_GROUP_BY
, a consulta correta (determinística) é:Para que a consulta seja executada com eficiência, é necessária uma indexação adequada.
Observe que, para fins de simplificação, removi o
LOWER()
, que na maioria dos casos, não será usado.fonte
order by
in subselect nas outras respostas não tem efeito algum.Faça um GROUP BY após ORDER BY envolvendo sua consulta com o GROUP BY assim:
fonte
time
, ou o mais novotime
, ou aleatoriamente?time DESC
e, em seguida, o agrupamento por pega a primeira (mais recente).De acordo com o padrão SQL, você não pode usar colunas não agregadas na lista de seleção. O MySQL permite tal uso (uless modo ONLY_FULL_GROUP_BY usado) mas o resultado não é previsível.
ONLY_FULL_GROUP_BY
Você deve primeiro selecionar fromEmail, MIN (ler) e, em seguida, com a segunda consulta (ou subconsulta) - Assunto.
fonte
Lutei com ambas as abordagens para consultas mais complexas do que as mostradas, porque a abordagem de subconsulta era terrivelmente ineficiente, não importa quais índices eu colocasse, e porque não consegui obter a auto-junção externa por meio do Hibernate
A melhor (e mais fácil) maneira de fazer isso é agrupar por algo que é construído para conter uma concatenação dos campos de que você precisa e, em seguida, extraí-los usando expressões na cláusula SELECT. Se você precisar fazer um MAX (), certifique-se de que o campo do qual deseja MAX () esteja sempre na extremidade mais significativa da entidade concatenada.
A chave para entender isso é que a consulta só pode fazer sentido se esses outros campos forem invariáveis para qualquer entidade que satisfaça Max (), portanto, em termos de classificação, as outras partes da concatenação podem ser ignoradas. Ele explica como fazer isso na parte inferior deste link. http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html
Se você puder obter um evento de inserção / atualização (como um gatilho) para pré-calcular a concatenação dos campos, você pode indexá-lo e a consulta será tão rápida como se o agrupamento por estivesse sobre apenas o campo que você realmente deseja MAX ( ) Você pode até mesmo usá-lo para obter o máximo de vários campos. Eu o uso para fazer consultas em árvores multidimensionais expressas como conjuntos aninhados.
fonte