showing - use distinct in sql with multiple columns




Existe alguma diferença entre GROUP BY e DISTINCT (16)

Eu aprendi algo simples sobre SQL no outro dia:

SELECT c FROM myTbl GROUP BY C

Tem o mesmo resultado de:

SELECT DISTINCT C FROM myTbl

O que eu estou curioso, há algo diferente na forma como um mecanismo de SQL processa o comando, ou eles são realmente a mesma coisa?

Eu pessoalmente prefiro a sintaxe distinta, mas tenho certeza que é mais por hábito do que por qualquer outra coisa.

EDIT: isso não é uma pergunta sobre agregados. O uso de GROUP BY com funções agregadas é entendido.


Qual é a diferença de um mero ponto de vista da funcionalidade de remoção duplicada

Além do fato de que, diferentemente do DISTINCT , GROUP BY permite agregar dados por grupo (o que foi mencionado por muitas outras respostas), a diferença mais importante na minha opinião é o fato de que as duas operações "acontecem" em duas etapas muito diferentes. a ordem lógica das operações que são executadas em uma SELECT .

Aqui estão as operações mais importantes:

  • FROM (incluindo JOIN , APPLY , etc.)
  • WHERE
  • GROUP BY (pode remover duplicatas)
  • Agregações
  • HAVING
  • Funções da janela
  • SELECT
  • DISTINCT (pode remover duplicatas)
  • UNION , INTERSECT , EXCEPT (pode remover duplicatas)
  • ORDER BY
  • OFFSET
  • LIMIT

Como você pode ver, a ordem lógica de cada operação influencia o que pode ser feito com ela e como ela influencia as operações subsequentes. Em particular, o fato de que a operação GROUP BY "acontece antes" da operação SELECT (a projeção) significa que:

  1. Não depende da projeção (o que pode ser uma vantagem)
  2. Não pode usar nenhum valor da projeção (o que pode ser uma desvantagem)

1. Não depende da projeção

Um exemplo em que não depende da projeção é se você deseja calcular as funções da janela em valores distintos:

SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film
GROUP BY rating

Quando executado contra o banco de dados Sakila , isso produz:

rating   rn
-----------
G        1
NC-17    2
PG       3
PG-13    4
R        5

O mesmo não poderia ser alcançado com DISTINCT facilmente:

SELECT DISTINCT rating, row_number() OVER (ORDER BY rating) AS rn
FROM film

Essa consulta está "errada" e produz algo como:

rating   rn
------------
G        1
G        2
G        3
...
G        178
NC-17    179
NC-17    180
...

Não é isso que queríamos. A operação DISTINCT "acontece após" a projeção, portanto, não podemos mais remover as classificações DISTINCT porque a função da janela já foi calculada e projetada. Para usar o DISTINCT , teríamos que aninhar essa parte da consulta:

SELECT rating, row_number() OVER (ORDER BY rating) AS rn
FROM (
  SELECT DISTINCT rating FROM film
) f

Nota: Neste caso em particular, podemos também usar DENSE_RANK()

SELECT DISTINCT rating, dense_rank() OVER (ORDER BY rating) AS rn
FROM film

2. Não pode usar nenhum valor da projeção

Uma das desvantagens do SQL é sua verbosidade às vezes. Pelo mesmo motivo que vimos antes (ou seja, a ordem lógica das operações), não podemos "facilmente" agrupar por algo que estamos projetando.

Este é um SQL inválido:

SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY name

Isso é válido (repetindo a expressão)

SELECT first_name || ' ' || last_name AS name
FROM customer
GROUP BY first_name || ' ' || last_name

Isso é válido também (aninhando a expressão)

SELECT name
FROM (
  SELECT first_name || ' ' || last_name AS name
  FROM customer
) c
GROUP BY name

Eu escrevi sobre este tópico mais em profundidade em um post


A eficiência funcional é totalmente diferente. Se você quiser selecionar apenas "valor de retorno", exceto duplicado, use distinto para melhor que grupo por. Porque "group by" inclui (classificação + remoção), "distinto" inclui (remoção)


A partir de uma perspectiva 'SQL the language', os dois constructos são equivalentes e qual deles você escolhe é uma daquelas escolhas de estilo de vida que todos nós temos que fazer. Eu acho que há um bom argumento para DISTINCT ser mais explícito (e, portanto, é mais considerado para a pessoa que herdará seu código, etc), mas isso não significa que a construção GROUP BY é uma opção inválida.

Eu acho que este 'GROUP BY é para agregados' é a ênfase errada. O folk deve estar ciente de que a função set (MAX, MIN, COUNT, etc) pode ser omitida para que eles possam entender a intenção do codificador quando for.

O otimizador ideal reconhecerá construções SQL equivalentes e sempre escolherá o plano ideal de acordo. Para o seu motor SQL de vida real de escolha, você deve testar :)

PS note que a posição da palavra-chave DISTINCT na cláusula select pode produzir resultados diferentes, por exemplo, contraste:

SELECT COUNT(DISTINCT C) FROM myTbl;

SELECT DISTINCT COUNT(C) FROM myTbl;

A resposta da MusiGenesis é funcionalmente correta no que diz respeito à sua questão, conforme declarado; O SQL Server é inteligente o suficiente para perceber que se você estiver usando "Agrupar por" e não usar funções agregadas, o que você realmente quer dizer é "Distinto" - e, portanto, gera um plano de execução como se você simplesmente usasse "

No entanto, acho que é importante notar que a resposta de Hank também - o tratamento descuidado de "Group By" e "Distinct" poderia levar a algumas armadilhas perniciosas se você não for cuidadoso. Não é totalmente correto dizer que isso "não é uma questão sobre agregados", porque você está perguntando sobre a diferença funcional entre duas palavras-chave de consulta SQL, uma delas destinada a ser usada com agregações e uma delas não é.

Um martelo pode trabalhar com um parafuso às vezes, mas se você tem uma chave de fenda à mão, por que se incomodar?

(para os fins desta analogia, Hammer : Screwdriver :: GroupBy : Distinct e screw => get list of unique values in a table column )


Espero que haja a possibilidade de diferenças sutis em sua execução. Verifiquei os planos de execução para duas consultas funcionalmente equivalentes ao longo dessas linhas no Oracle 10g:

core> select sta from zip group by sta;

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    58 |   174 |    44  (19)| 00:00:01 |
|   1 |  HASH GROUP BY     |      |    58 |   174 |    44  (19)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| ZIP  | 42303 |   123K|    38   (6)| 00:00:01 |
---------------------------------------------------------------------------

core> select distinct sta from zip;

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |    58 |   174 |    44  (19)| 00:00:01 |
|   1 |  HASH UNIQUE       |      |    58 |   174 |    44  (19)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| ZIP  | 42303 |   123K|    38   (6)| 00:00:01 |
---------------------------------------------------------------------------

A operação do meio é ligeiramente diferente: "HASH GROUP BY" vs. "HASH UNIQUE", mas os custos estimados, etc., são idênticos. Em seguida, executei-os com o rastreio e as contagens de operações reais foram as mesmas para ambos (exceto que o segundo não precisou fazer nenhuma leitura física devido ao armazenamento em cache).

Mas acho que porque os nomes das operações são diferentes, a execução seguiria caminhos de código um pouco diferentes e isso abre a possibilidade de diferenças mais significativas.

Eu acho que você deve preferir a sintaxe DISTINCT para este propósito. Não é apenas hábito, indica mais claramente o propósito da consulta.


Eu li todos os comentários acima, mas não vi ninguém apontando para a principal diferença entre Group By e Distinct além do bit de agregação.

Distinto retorna todas as linhas e, em seguida, desduplica-as, enquanto Agrupar Desduplica as linhas à medida que são lidas pelo algoritmo, uma a uma.

Isso significa que eles podem produzir resultados diferentes!

Por exemplo, os códigos abaixo geram resultados diferentes:

SELECT distinct ROW_NUMBER() OVER (ORDER BY Name), Name FROM NamesTable

 SELECT ROW_NUMBER() OVER (ORDER BY Name), Name FROM NamesTable
GROUP BY Name

Se houver 10 nomes na tabela em que 1 é uma duplicata de outra, a primeira consulta retorna 10 linhas, enquanto a segunda retorna 9 linhas.

A razão é o que eu disse acima para que eles possam se comportar de maneira diferente!


Eu tive essa pergunta antes, eu preciso acrescentar três colunas da minha tabela de 4 milhões de linhas (as três colunas em uma nova coluna de uma nova tabela), mas apenas as diferentes.

Então eu corri meu procedimento armazenado que contém esta consulta com o método 'group by' e levou 32 minutos. Então eu corri de novo, mas com método 'distinto' e demorou 25 minutos.

É o mesmo resultado, mas foi um pouco mais rápido com o segundo método


GROUP BY tem um significado muito específico que é distinto (heh) da função DISTINCT.

GROUP BY faz com que os resultados da consulta sejam agrupados usando a expressão escolhida, as funções agregadas podem ser aplicadas e elas agirão em cada grupo, em vez de todo o conjunto de resultados.

Aqui está um exemplo que pode ajudar:

Dada uma tabela que se parece com isso:

name
------
barry
dave
bill
dave
dave
barry
john

Esta consulta:

SELECT name, count(*) AS count FROM table GROUP BY name;

Produzirá a saída assim:

name    count
-------------
barry   2
dave    3
bill    1
john    1

O que é obviamente muito diferente do uso de DISTINCT. Se você quiser agrupar seus resultados, use GROUP BY, se quiser apenas uma lista exclusiva de uma coluna específica, use DISTINCT. Isso dará ao seu banco de dados a oportunidade de otimizar a consulta para suas necessidades.


Nessa consulta específica, não há diferença. Mas, claro, se você adicionar colunas agregadas, será necessário usar group by.



Por favor, não use GROUP BY quando você quer dizer DISTINCT, mesmo que eles funcionem da mesma forma. Estou assumindo que você está tentando eliminar milissegundos de consultas, e devo salientar que o tempo do desenvolvedor é muito mais caro do que o tempo do computador.


Se você estiver usando um GROUP BY sem qualquer função agregada, internamente ele será tratado como DISTINCT, portanto, neste caso, não há diferença entre GROUP BY e DISTINCT.

Mas quando você é fornecido com a cláusula DISTINCT, é melhor usá-lo para localizar seus registros exclusivos, porque o objetivo do GROUP BY é conseguir a agregação.


Use DISTINCT se você quiser apenas remover duplicatas. Use GROUPY BY se quiser aplicar operadores agregados ( MAX , SUM , GROUP_CONCAT , ... ou uma cláusula HAVING ).


Você só está percebendo isso porque está selecionando uma única coluna.

Tente selecionar dois campos e veja o que acontece.

Agrupar por destina-se a ser usado assim:

SELECT name, SUM(transaction) FROM myTbl GROUP BY name

O que mostraria a soma de todas as transações para cada pessoa.


Na perspectiva de Teradata :

Do ponto de vista do conjunto de resultados, não importa se você usa DISTINCT ou GROUP BY no Teradata. A resposta definida será a mesma.

Do ponto de vista do desempenho, não é o mesmo.

Para entender o que impacta o desempenho, você precisa saber o que acontece no Teradata ao executar uma instrução com DISTINCT ou GROUP BY.

No caso de DISTINCT, as linhas são redistribuídas imediatamente sem qualquer pré-agregação, enquanto no caso de GROUP BY, em uma primeira etapa uma pré-agregação é feita e somente então os valores únicos são redistribuídos pelos AMPs.

Não pense agora que o GROUP BY é sempre melhor do ponto de vista do desempenho. Quando você tem muitos valores diferentes, a etapa de pré-agregação do GROUP BY não é muito eficiente. Teradata tem que classificar os dados para remover duplicatas. Nesse caso, pode ser melhor para a redistribuição primeiro, ou seja, use a instrução DISTINCT. Somente se houver muitos valores duplicados, a instrução GROUP BY provavelmente será a melhor opção apenas quando a etapa de redução de redundância ocorrer, após a redistribuição.

Em resumo, DISTINCT vs. GROUP BY em Teradata significa:

GROUP BY -> para muitos duplicados DISTINCT -> não ou apenas alguns duplicados. Às vezes, ao usar DISTINCT, você fica sem espaço no spool em um AMP. A razão é que a redistribuição ocorre imediatamente e a distorção pode fazer com que as AMPs fiquem sem espaço.

Se isso acontecer, você provavelmente terá uma chance melhor com GROUP BY, pois as duplicatas já foram removidas em uma primeira etapa e menos dados serão movidos pelas AMPs.


GROUP BY permite que você use funções agregadas, como AVG , MAX , MIN , SUM e COUNT . Outra mão DISTINCT apenas remove duplicatas.

Por exemplo, se você tiver vários registros de compra e quiser saber quanto foi gasto por cada departamento, poderá fazer algo como:

SELECT department, SUM(amount) FROM purchases GROUP BY department

Isso fornecerá uma linha por departamento, contendo o nome do departamento e a soma de todos os valores em todas as linhas desse departamento.







distinct