Por que não funciona com GROUP BY
SELECT *
não pode ser usado com GROUP BY
; é SQL inválido. GROUP BY
não seleciona linhas da tabela. Ele cria grupos de linhas usando as expressões fornecidas e, a partir de cada grupo, gera um novo registro e calcula cada coluna desse novo registro usando os valores envolvidos na expressão. As colunas que aparecem no
SELECT
cláusula deve satisfazer uma das seguintes regras:- também aparecem em
GROUP BY
cláusula; - são usados com
GROUP BY
funções agregadas ; - são funcionalmente dependentes das colunas que aparecem no
GROUP BY
cláusula.
Enquanto
*
é um atalho para todos os nomes de coluna da(s) tabela(s) usada(s) pela consulta, para sua consulta apenas o user
coluna satisfaça um dos requisitos acima. Antes da versão 5.7.5 O MySQL não implementou a terceira regra acima. Ele costumava aceitar consultas que continham no
SELECT
colunas de cláusulas que não seguem nenhuma das cláusulas GROUP BY
requisitos. O valor retornado pela consulta para essas colunas foi indeterminado
. Desde a versão 5.7.5, o MySQL rejeita o
GROUP BY
consultas que satisfazem os requisitos. A solução
De qualquer forma, a solução para o seu problema não envolve
GROUP BY
. Isso pode ser feito facilmente usando um LEFT JOIN
com as condições corretas:SELECT lc.*
FROM comments lc # 'lc' from 'last comment'
LEFT JOIN comments nc # 'nc' from 'newer comment'
ON lc.user = nc.user # both comments belong to the same user
AND lc.id < nc.id # 'nc' is newer than 'lc'
WHERE nc.id IS NULL # there is no 'newer comment'
ORDER BY lc.id DESC
LIMIT 10
Como funciona
Ele se junta à tabela
comments
, alias como lc
("lc" do "último comentário" de um usuário) contra si mesmo, alias como nc
("nc" de "comentário mais recente"). A cláusula join corresponde a cada entrada de lc
com todas as entradas de nc
que pertencem ao mesmo usuário (lc.user = nc.user
) e são mais recentes (lc.id < nc.id
; Presumi que os IDs são atribuídos sequencialmente e os comentários mais recentes têm valores maiores para id
). O uso de
LEFT JOIN
garante que cada linha de lc
aparece no resultado da junção, mesmo quando nenhuma linha correspondente é encontrada em nc
(porque não há comentários mais recentes do mesmo usuário). Neste caso, NULL
é usado em vez dos campos de nc
. O WHERE
cláusula mantém no resultado final apenas as linhas que possuem NULL
em nc.id
; isso significa que no lc
parte eles contêm o comentário mais recente de cada usuário. O
SELECT
cláusula contém todos os campos de lc
(os de nc
são todos NULL
, de qualquer forma). O ORDER BY
cláusula pode ser usada para classificar o conjunto de resultados. ORDER BY lc.id DESC
coloca os comentários mais recentes primeiro e o LIMIT
cláusula mantém o resultado definido em um tamanho decente.