ID FirstName LastName
1 John Doe
2 Bugs Bunny
3 John Johnson
Quero selecionar DISTINCT
resultados da FirstName
coluna, mas preciso do correspondente ID
e LastName
.
O conjunto de resultados precisa mostrar apenas um John
, mas com um ID
de 1 e um LastName
de Doe.
DISTINCT
não é uma função. Todas as respostas comDISTINCT()
estão erradas. O erro será exibido quando você não o colocar depoisSELECT
.ALL
respostas usando parênteses após a palavra distinto estão realmente erradas. Distinct NÃO é uma função, portanto não pode aceitar um parâmetro. Os parênteses após distintos são simplesmente ignorados. A menos que você esteja usando o PostgreSQL, onde os parênteses formarão um "tipo de dados complexo"Respostas:
tente esta consulta
fonte
5.7.5+
para a mudança deGROUP BY
manuseioA
DISTINCT
palavra-chave não funciona da maneira que você espera. Quando você usa,SELECT DISTINCT col1, col2, col3
na verdade, seleciona todas as tuplas {col1, col2, col3} exclusivas.fonte
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 comONLY_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 aLEFT 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
Resultado
Ordem decrescente (ZA)
Para recuperar o nome distinto ordenado pelo sobrenome do ZA
Inquerir
Resultado
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
Inquerir
Resultado
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 deGROUP 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
oulastname
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
Inquerir
Resultado
Comparação
Para demonstrar resultados inesperados ao usar
GROUP BY
em combinação comORDER BY
Inquerir
Resultado
fonte
Ordering is done after grouping.
, portanto, não neste caso de uso, o MariaDB ignora ORDER BY em subconsultas (conforme o padrão SQL) sem aLIMIT
. Você iria querer usar umWindow Function
Para mais esclarecimentos, você deve fazer sua pergunta no Stackexchange DBA , pois esta é uma questão relativa ao MySQLGROUP BY
possível selecionar qualquer valor no conjunto de dados agrupados, a menos que uma função agregada seja usada nessas colunas para forçar um valor específico. Portanto,lastname
ouid
pode vir de qualquer uma das linhas ordenadas. O exemplo de subconsulta original era aceitável por padrão,MySQL <= 5.7.4
mas tecnicamente ainda sofre com o problema. EnquantoORDER BY
isso ajuda a impedir uma seleção aleatória, ainda é teoricamente possível, mas com uma probabilidade significativamente menor do que sem o uso daORDER BY
subconsulta.fonte
HAVING
fez minha consulta 50% mais lenta.fonte
E se
fonte
Não tenho certeza se você pode fazer isso com o MySQL, mas você pode usar um CTE no T-SQL
Caso contrário, talvez você precise usar uma tabela temporária.
fonte
Como apontado por fyrye , a resposta aceita refere-se a versões mais antigas do MySQL nas quais
ONLY_FULL_GROUP_BY
ainda não haviam sido introduzidas. Com o MySQL 8.0.17 (usado neste exemplo), a menos que você desabilite,ONLY_FULL_GROUP_BY
você receberá a seguinte mensagem de erro:Uma maneira de contornar isso não mencionada por fyrye , mas descrita em https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html , é aplicar a
ANY_VALUE()
função às colunas que são não naGROUP BY
cláusula (id
elastName
neste exemplo):Conforme escrito nos documentos acima mencionados,
fonte
ANY_VALUE()
pois minhas respostas e comentários estão focados na prevenção de conjuntos de resultados ambíguos e imprevisíveis. Como o nome da função sugere, pode resultar na recuperação de qualquer valor das linhas selecionadas. Eu sugeriria usarMAX
ou emMIN
vez disso.Lembre-se de que ao usar o grupo por e ordenar, o MySQL é o ÚNICO banco de dados que permite que colunas sejam usadas no grupo por e / ou ordem por parte que não fazem parte da instrução select.
Por exemplo: selecione coluna1 do grupo de tabelas por coluna2 e ordene por coluna3
Isso não voará em outros bancos de dados como Postgres, Oracle, MSSQL, etc. Você precisaria fazer o seguinte nesses bancos de dados
selecione coluna1, coluna2, coluna3 do grupo de tabelas por coluna2, ordem por coluna3
Apenas algumas informações, caso você migre seu código atual para outro banco de dados ou comece a trabalhar em outro banco de dados e tente reutilizar o código.
fonte
Você pode usar agrupar por para exibir valores distintos e também campos correspondentes.
Agora você tem uma saída como esta:
Se você quiser responder como
então use esta consulta,
fonte
Seria a melhor aposta IMO
fonte
fonte
DISTINCT()
não é uma função. DISTINCT e GROUP BY também estão fazendo a mesma coisa, então não há razão para colocar os dois.