Para evitar resultados potencialmente inesperados ao usar GROUP BY
sem uma função agregada, como é usado na resposta aceita , porque o MySQL é livre para recuperar QUALQUER valor dentro do conjunto de dados que está sendo agrupado quando não estiver usando uma função agregada [sic] e problemas com ONLY_FULL_GROUP_BY
. Considere usar uma associação de exclusão.
Associação de exclusão - entidades não ambíguas
Supondo que o nome e o sobrenome sejam indexados exclusivamente (sem ambiguidade) , uma alternativa GROUP BY
é classificar usando a LEFT JOIN
para filtrar o conjunto de resultados, também conhecido como exclusão JOIN.
Ver demonstração
Ordem crescente (AZ)
Para recuperar o nome distinto ordenado pelo sobrenome de AZ
Inquerir
SELECT t1.*
FROM table_name AS t1
LEFT JOIN table_name AS t2
ON t1.firstname = t2.firstname
AND t1.lastname > t2.lastname
WHERE t2.id IS NULL;
Resultado
| id | firstname | lastname |
|----|-----------|----------|
| 2 | Bugs | Bunny |
| 1 | John | Doe |
Ordem decrescente (ZA)
Para recuperar o nome distinto ordenado pelo sobrenome do ZA
Inquerir
SELECT t1.*
FROM table_name AS t1
LEFT JOIN table_name AS t2
ON t1.firstname = t2.firstname
AND t1.lastname < t2.lastname
WHERE t2.id IS NULL;
Resultado
| id | firstname | lastname |
|----|-----------|----------|
| 2 | Bugs | Bunny |
| 3 | John | Johnson |
Você pode solicitar os dados resultantes conforme desejado.
Junção de exclusão - entidades ambíguas
Se a combinação de nome e sobrenome não for exclusiva (ambígua) e você tiver várias linhas dos mesmos valores, poderá filtrar o conjunto de resultados incluindo uma condição OR nos critérios JOIN para também filtrar por ID.
Ver demonstração
dados table_name
(1, 'John', 'Doe'),
(2, 'Bugs', 'Bunny'),
(3, 'John', 'Johnson'),
(4, 'John', 'Doe'),
(5, 'John', 'Johnson')
Inquerir
SELECT t1.*
FROM table_name AS t1
LEFT JOIN table_name AS t2
ON t1.firstname = t2.firstname
AND (t1.lastname > t2.lastname
OR (t1.firstname = t1.firstname AND t1.lastname = t2.lastname AND t1.id > t2.id))
WHERE t2.id IS NULL;
Resultado
| id | firstname | lastname |
|----|-----------|----------|
| 1 | John | Doe |
| 2 | Bugs | Bunny |
Subconsulta ordenada
EDITAR
Minha resposta original usando uma subconsulta ordenada foi escrita antes do MySQL 5.7.5 , que não é mais aplicável, devido às alterações no ONLY_FULL_GROUP_BY
. Em vez disso, use os exemplos de junção de exclusão acima.
Também é importante notar; Quando ONLY_FULL_GROUP_BY
está desabilitado (comportamento original anterior ao MySQL 5.7.5) , o uso de GROUP BY
sem uma função agregada pode produzir resultados inesperados, porque o MySQL é livre para escolher QUALQUER valor dentro do conjunto de dados que está sendo agrupado [sic] .
Significa que um valor ID
ou lastname
pode ser recuperado que não está associado à firstname
linha recuperada .
AVISO
O MySQL GROUP BY
pode não produzir os resultados esperados quando usado comORDER BY
Consulte o Exemplo de Caso de Teste
O melhor método de implementação, para garantir os resultados esperados, é filtrar o escopo do conjunto de resultados usando uma subconsulta ordenada.
dados table_name
(1, 'John', 'Doe'),
(2, 'Bugs', 'Bunny'),
(3, 'John', 'Johnson')
Inquerir
SELECT * FROM (
SELECT * FROM table_name ORDER BY ID DESC
) AS t1
GROUP BY FirstName
Resultado
| ID | first | last |
|----|-------|---------|
| 2 | Bugs | Bunny |
| 3 | John | Johnson |
Comparação
Para demonstrar resultados inesperados ao usar GROUP BY
em combinação comORDER BY
Inquerir
SELECT * FROM table_name GROUP BY FirstName ORDER BY ID DESC
Resultado
| ID | first | last |
|----|-------|-------|
| 2 | Bugs | Bunny |
| 1 | John | Doe |