Pergunta

Eu aprendi algo simples sobre SQL no outro dia:

SELECT c FROM myTbl GROUP BY C

tem o mesmo resultado como:

SELECT DISTINCT C FROM myTbl

O que eu estou curioso de, há diferentes nada na forma de um motor SQL processa o comando, ou são realmente a mesma coisa?

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

EDIT: Esta não é uma pergunta sobre agregados. O uso de GROUP BY com funções de agregação é compreendido.

Foi útil?

Solução

MusiGenesis ' resposta é funcionalmente o correto no que diz respeito à sua pergunta como indicado; o SQL Server é bastante inteligente para perceber que, se você estiver usando o "Group By" e não utilizar quaisquer funções de agregação, então o que você realmente quer dizer é "distinto" - e, portanto, ele gera um plano de execução como se você tivesse usado simplesmente "Distinto . "

No entanto, eu acho que é importante notar Hank a resposta de bem - tratamento desdenhoso de 'Group By' e 'distinto' poderia levar a algumas armadilhas perniciosas para baixo da linha se você não tiver cuidado. Não é inteiramente correto dizer que esta "não é uma pergunta sobre agregados" porque você está perguntando sobre a diferença funcional entre duas palavras-chave de consulta SQL, um dos quais é feito para ser usado com agregados e um de que não é.

Um martelo pode trabalhar para conduzir um parafuso, por vezes, mas se você tem uma chave de fenda acessível, por que se preocupar?

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

Outras dicas

GROUP BY permite usar funções agregadas, como AVG, MAX, MIN, SUM e COUNT. Por outro lado DISTINCT apenas remove duplicatas.

Por exemplo, se você tem um monte de registros de compra, e você quer saber quanto foi gasto por cada departamento, você pode fazer algo como:

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

Isto lhe dará uma linha por departamento, contendo o nome do departamento e a soma de todos os valores amount em todas as linhas para esse departamento.

Não há nenhuma diferença (em SQL Server, pelo menos). Ambas as consultas usar o mesmo plano de execução.

http://sqlmag.com/database-performance-tuning/distinct- vs grupo

Talvez haja é a diferença, se houver sub-consultas envolvidos:

http://blog.sqlauthority.com/2007/03/29/sql-server-difference-between-distinct-and-group-by-distinct-vs-group-by/

Não há nenhuma diferença (Oracle-style):

http: // AskTom ? .oracle.com / pls / AskTom / f p = 100: 11: 0 :::: P11_QUESTION_ID: 32961403234212

Use DISTINCT se você apenas deseja remover duplicatas. Use GROUPY BY se você deseja aplicar operadores de agregação (MAX, SUM, GROUP_CONCAT, ..., ou uma cláusula HAVING).

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

Além do fato de que DISTINCT ao contrário, GROUP BY permite agregar dados por grupo (que foi mencionado por muitas outras respostas), a diferença mais importante na minha opinião é o fato de que as duas operações "acontecer" em dois passos muito diferentes no ordem lógica das operações que são executadas em um comunicado SELECT .

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

  • FROM (incluindo JOIN, APPLY, etc.)
  • WHERE
  • GROUP BY (pode remover duplicatas)
  • As 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 influências de operação que pode ser feito com ele e como ele influencia as operações subsequentes. Em particular, o facto da operação GROUP BY "acontece antes" a operação SELECT (a projeção) significa que:

  1. não depende da projecção (que pode ser uma vantagem)
  2. não pode usar quaisquer valores da projecção (que pode ser uma desvantagem)

1. Ele não depende da projeção

Um exemplo onde não dependendo da projeção é útil é se você quiser funções da janela calcular em valores distintos:

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

Quando executado contra o Sakila banco de dados , este resulta em:

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 é "errado" e rendimentos algo como:

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

Este não é o que queríamos. A operação DISTINCT "acontece depois" a projeção, por isso não podemos mais classificações de remover DISTINCT porque a função janela foi já calculada e projetada. Para utilizar DISTINCT, teríamos de ninho que parte da consulta:

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

Side-note: neste caso particular, nós também podemos usar DENSE_RANK()

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

2. Ele não pode usar quaisquer valores a partir da projeção

Uma das desvantagens do SQL é a sua verbosidade às vezes. Pela mesma razão, como o que vimos antes (ou seja, a ordem lógica de operações), que não pode "facilmente" grupo por algo que está a projectar.

Esta é SQL inválida:

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 (nidificação a expressão)

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

Eu escrevi sobre este tema com mais profundidade em um post

Espero que existe a possibilidade de diferenças sutis em sua execução. Eu verifiquei os planos de execução de duas consultas funcionalmente equivalentes ao longo destas linhas em 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 é um pouco diferente: "GROUP BY HASH" versus "hash exclusivo", mas os custos estimados etc. são idênticos. Eu, então, executado estes com rastreamento on e as contagens operação real eram as mesmas para ambos (exceto que o segundo não tem que fazer qualquer leituras físicas devido ao cache).

Mas eu acho que, como os nomes de operação são diferentes, a execução se seguiria um pouco diferentes caminhos de código e que abre a possibilidade de diferenças mais significativas.

Eu acho que você deve preferir a sintaxe distinta para esta finalidade. Não é apenas hábito, isso indica mais claramente a finalidade da consulta.

Para a consulta você postou, eles são idênticos. Mas para outras consultas que não pode ser verdade.

Por exemplo, não é o mesmo que:

SELECT C FROM myTbl GROUP BY C, D

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

retornos distintos todas as linhas, em seguida, duplicatas des-los enquanto Group By de-desduplicar as linhas como eles são lidos por aquele algoritmo por um.

Isso significa que eles podem produzir resultados diferentes!

Por exemplo, a seguir códigos geram diferentes resultados:

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 existem 10 nomes na mesa onde 1 das quais é uma duplicata de outro, em seguida, a primeira consulta retorna 10 linhas, enquanto que a segunda volta de consultas 9 linhas.

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

Se você usar distinta com várias colunas, o conjunto de resultados não serão agrupados como ele vai com GROUP BY, e você não pode usar funções agregadas com distintas.

Eles têm semânticas diferentes, mesmo se acontecer de ter resultados equivalentes em seus dados particular.

GROUP BY tem um significado muito especial, que é distinta (heh) a partir da função distinta.

GROUP BY faz com que os resultados da consulta para ser agrupadas utilizando a expressão escolhido, funções de agregação pode, então, ser aplicada, e estes irão actuar 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;

Será produzir uma saída como esta:

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

O que é obviamente muito diferente de usar distintas. Se você quer agrupar seus resultados, use GROUP BY, se você quiser apenas uma lista única de uma coluna específica, use distintas. Isto dará a seu banco de dados uma oportunidade para otimizar a consulta para as suas necessidades.

Por favor, não use GROUP BY quando você quer dizer DISTINCT, mesmo se acontecer a trabalhar da mesma. Estou assumindo que você está tentando raspar milissegundos a partir de consultas, e eu tenho que salientar que o tempo desenvolvedor é ordens de magnitude mais caro do que o tempo de computador.

Se você estiver usando um GROUP BY sem qualquer função de agregação, em seguida, internamente ele vai tratados como distintos, 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 encontrar seus registros exclusivos porque o objetivo de GROUP BY é conseguir a agregação.

grupo, é usado em operações agregadas - como quando você deseja obter uma contagem de Bs discriminadas por coluna C

select C, count(B) from myTbl group by C

distinta é o que parece -. Você começa linhas exclusivas

No sql server 2005, parece que o otimizador de consulta é capaz de otimizar afastado a diferença nos exemplos simplistas eu corri. Não sei se você pode contar com isso em todas as situações, no entanto.

Nesse consulta particular, não há diferença. Mas, é claro, se você adicionar as colunas agregadas, então você vai ter que grupo de uso por.

A partir de um 'SQL a linguagem' perspectiva as duas construções são equivalentes e que você escolher é uma dessas escolhas 'estilo de vida' que todos nós temos que fazer. Eu acho que é um bom caso para ser distinto mais explícito (e, portanto, é mais atencioso para com a pessoa que vai herdar seu código etc), mas isso não significa que o GROUP BY construção é uma escolha inválida.

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

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

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

SELECT COUNT(DISTINCT C) FROM myTbl;

SELECT DISTINCT COUNT(C) FROM myTbl;

Em Teradata perspectiva :

Do ponto de vista conjunto de resultados, não importa se você usar DISTINCT ou GROUP BY em Teradata. O conjunto de respostas será o mesmo.

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

Para entender o que afeta o desempenho, você precisa saber o que acontece na Teradata ao executar uma declaração com DISTINCT ou GROUP BY.

No caso de DISTINCT, as linhas são redistribuídos imediatamente, sem qualquer lugar preaggregation tomada, enquanto que no caso de GROUP BY, numa primeira etapa a preaggregation é feito e só então são os valores exclusivos redistribuídos através das AMPs.

Não pense agora que GROUP BY é sempre melhor do ponto de vista do desempenho. Quando você tem muitos valores diferentes, o passo preaggregation de GROUP BY não é muito eficiente. Teradata tem para classificar os dados para duplicatas remover. Neste caso, pode ser melhor para a redistribuição em primeiro lugar, ou seja, usar a declaração distinta. Só se houver muitos valores duplicados, a instrução GROUP BY é provavelmente a melhor escolha como apenas uma vez o passo desduplicação ocorre, depois de redistribuição.

Em suma, GROUP vs. DISTINCT BY em meio Teradata:

GROUP BY -> Para muitas duplicatas DISTINCT -> nenhuma ou apenas algumas duplicatas. Às vezes, quando se usa DISTINCT, você correr para fora do carretel espaço em um AMP. A razão é que a redistribuição ocorre imediatamente, e desviando poderia causar AMPs a correr para fora do espaço.

Se isso acontecer, você tem provavelmente a melhor chance com GROUP BY, como duplicatas já são removidos em um primeiro passo, e menos dados são movidos através das AMPs.

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

Tente selecionar dois campos e ver o que acontece.

Grupo por se destina a ser usado como este:

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

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

Eu sei que é um post antigo. Mas acontece que eu tinha uma consulta que grupo usou por apenas para retornar valores distintos ao usar essa consulta nos relatórios sapo e Oracle tudo funcionou bem, eu quero dizer uma vez boa resposta. Quando migrou do Oracle 9i para 11g o tempo de resposta em Toad foi excelente, mas no reporte que demorou cerca de 35 minutos para terminar o relatório ao usar versão anterior que demorou cerca de 5 minutos.

A solução foi mudar o grupo, e usar DISTINCT e agora o relatório é executado em cerca de 30 segundos.

Espero que este seja útil para alguém com a mesma situação.

A maneira que eu sempre entendi é que o uso distinto é o mesmo que o agrupamento de todos os campos que você selecionou na ordem que você selecionou-los.

ou seja:

select distinct a, b, c from table;

é o mesmo que:

select a, b, c from table group by a, b, c

eficiência Funtional é totalmente diferente. Se você gostaria de selecionar apenas "valor de retorno", exceto um duplicado, utilize distinta é melhor do que agrupar. Porque "grupo por" incluem (triagem + removendo), "distinto" incluem (remoção)

Em Hive (HQL), grupo por pode ser muito mais rápido do que distintos, porque o primeiro não exige comparando todos os campos na tabela. Consulte https://sqlperformance.com/2017 / 01 / t-SQL-consultas / surpresas-suposições-group-by-distinta .

Não há nenhuma diferença significativa entre o grupo e por cláusula distinta, excepto o uso de funções de agregação. Ambos podem ser usados ??para distinguir os valores mas se no ponto de vista do desempenho grupo por é melhor. Quando palavra-chave distinta é usada, internamente usado operação de classificação que pode ser vista no plano de execução.

Tente exemplo simples

Declare @tmpresult mesa ( Id tinyint )

Inserir em @tmpresult Selecione 5 toda a União Selecione 2 toda a União Selecione 3 toda a União Selecione 4

Selecione distinta Eu iria De @tmpresult

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top