Por que não SELECT DISTINCT * FROM tablefunciona para você?
ypercubeᵀᴹ
19
Se sua tabela tiver um PK, todas as linhas deverão ser distinctpor definição. Se você está tentando apenas selecionar, DISTINCT field1mas de alguma forma retornar todas as outras colunas, o que deve acontecer com as colunas que possuem mais de um valor para um field1valor específico ? Você precisaria usar GROUP BYe algum tipo de agregação nas outras colunas, por exemplo.
Martin Smith
11
Se você deseja linhas repetidas e não apenas linhas distintas, remova a palavra-chave distinta.
Hyperboreus
2
Você poderia dar um exemplo de como você espera que os resultados sejam? Até o momento, não consigo entender sua consulta desejada.
Ocasionalmente, pode ser escrito com uma declaração distinta:
selectdistincton field1 *fromtable
Na maioria das plataformas, no entanto, nenhuma das opções acima funcionará porque o comportamento nas outras colunas não é especificado. (O primeiro funciona no MySQL, se é isso que você está usando.)
Você pode buscar os campos distintos e escolher uma única linha arbitrária a cada vez.
Em algumas plataformas (por exemplo, PostgreSQL, Oracle, T-SQL), isso pode ser feito diretamente usando as funções da janela:
Em outros (MySQL, SQLite), você precisará escrever subconsultas que farão com que você junte toda a tabela consigo ( exemplo ), por isso não é recomendado.
A consulta não irá analisar para mim e dá um erro: The ranking function "row_number" must have an ORDER BY clause. Precisamos adicionar ordem por cláusula após partição por campo1. Portanto, a consulta correta será: select * from ( select *, row_number() over (partition by field1 order by orderbyFieldName) as row_number from table ) as rows where row_number = 1
Ankur-m
11
Obrigado! Eu estava no mesmo problema e a solução foi a: GROUP BY
Joaquin Iurchuk 13/11/2015
2
Também no Oracle (Oracle SQL Developer) você não pode especificar select *, row_number() over (partition by field1 order by field2) as row_number from table. Você tem que usar explicitamente nome da tabela / alias na consulta seleçãoselect **table**.*, row_number() over (partition by field1 order by field2) as row_number from table
meta4
11
@jarlh: Pode ser ... hoje. Como você pode notar, essa resposta tem quase 7 anos, um momento em que esse não era o caso, na medida em que posso me lembrar de quando eu estava ativo. Você pode marcar e / ou editar a resposta novamente, se achar necessário.
Denis de Bernardy
2
select distinct on (field1) * from table; trabalha também no PostgreSQL
Chilianu Bogdan
61
A partir da formulação da sua pergunta, entendo que você deseja selecionar os valores distintos para um determinado campo e para cada um desses valores ter todos os outros valores da coluna na mesma linha listados. A maioria dos DBMSs não permitirá isso com nem DISTINCTnem GROUP BYporque o resultado não é determinado.
Pense assim: se o seu field1ocorrer mais de uma vez, qual o valor de field2será listado (dado que você tem o mesmo valor field1em duas linhas, mas dois valores distintos field2nessas duas linhas).
No entanto, você pode usar funções agregadas (explicitamente para todos os campos que deseja que sejam mostrados) e usar um em GROUP BYvez de DISTINCT:
+1 para esta solução. Para que possamos fazer SELECT field1, MIN(field2), MIN(field3), MIN(field4), .... FROM table GROUP BY field1, e os campos 2, 3, 4 ,,, não precisam ser números inteiros (ou outros dígitos), eles também podem ser campos de caracteres
perscreva
Estava funcionando bem até ficar preso em uma coluna booleana. Os valores da coluna MIN (Dinâmico) são modificados para false, mesmo que sejam verdadeiros. Qualquer outra função agregada disponível para tratar boolean - signonsridhar há 6 minutos. Sum (dinâmico) alterado false para 1
signonsridhar 22/08/16
11
Ótima sugestão, levou-me à minha solução, que eu acho mais universal - dê uma olhada!
Garrett Simpson
@signonsridhar converte seu booleano em uma int e use sum; por exemplo:sum(cast(COL as int)) > 0
Drew
26
Se entendi seu problema corretamente, é semelhante ao que acabei de ter. Você deseja limitar a usabilidade do DISTINCT a um campo especificado, em vez de aplicá-lo a todos os dados.
Se você usar GROUP BY sem uma função agregada, em qualquer campo que você GROUP BY será seu arquivo DISTINCT.
Se você fizer sua consulta:
SELECT*fromtableGROUPBY field1;
Ele mostrará todos os seus resultados com base em uma única instância do campo1.
Por exemplo, se você tiver uma tabela com nome, endereço e cidade. Uma única pessoa tem vários endereços registrados, mas você só quer um único endereço para a pessoa, pode consultar da seguinte maneira:
SELECT*FROM persons GROUPBY name;
O resultado será que apenas uma instância desse nome aparecerá com seu endereço e a outra será omitida da tabela resultante. Cuidado: se seus arquivos tiverem valores atômicos como firstName, lastName, você deseja agrupar por ambos.
SELECT*FROM persons GROUPBY lastName, firstName;
porque se duas pessoas tiverem o mesmo sobrenome e você agrupar apenas por sobrenome, uma dessas pessoas será omitida dos resultados. Você precisa manter essas coisas em consideração. Espero que isto ajude.
Por que há Caliasquando ele pode funcionar sem ele? na linhaFROM dbo.TABLE AS C
Talha 02/10
2
Eu acredito que isso se deve ao meu uso do RedGate SQLPrompt. Do jeito que eu o configurei, ele sempre adiciona aliases - mesmo que desnecessários. Está lá "por precaução" #
Stormy
Isso pareceu promissor para mim, mas ainda trouxe de volta todas as linhas, não o campo distinto1. :(
Michael Fever
13
Essa é uma pergunta muito boa. Eu já li algumas respostas úteis aqui, mas provavelmente posso adicionar uma explicação mais precisa.
Reduzir o número de resultados da consulta com uma instrução GROUP BY é fácil, desde que você não consulte informações adicionais. Vamos supor que você tenha a seguinte tabela 'locais'.
--country-- --city--
France Lyon
Poland Krakow
France Paris
France Marseille
Italy Milano
Agora a consulta
SELECT country FROM locations
GROUPBY country
vai resultar em:
--country--
France
Poland
Italy
No entanto, a seguinte consulta
SELECT country, city FROM locations
GROUPBY country
... gera um erro no MS SQL, porque como seu computador pode saber qual das três cidades francesas "Lyon", "Paris" ou "Marselha" você deseja ler no campo à direita de "França"?
Para corrigir a segunda consulta, você deve adicionar essas informações. Uma maneira de fazer isso é usar as funções MAX () ou MIN (), selecionando o valor maior ou menor entre todos os candidatos. MAX () e MIN () não são apenas aplicáveis aos valores numéricos, mas também comparam a ordem alfabética dos valores das strings.
SELECT country, MAX(city)FROM locations
GROUPBY country
vai resultar em:
--country-- --city--
France Paris
Poland Krakow
Italy Milano
ou:
SELECT country, MIN(city)FROM locations
GROUPBY country
vai resultar em:
--country-- --city--
France Lyon
Poland Krakow
Italy Milano
Essas funções são uma boa solução, desde que você esteja bem ao selecionar seu valor nas extremidades da ordem alfabética (ou numérica). Mas e se não for esse o caso? Vamos supor que você precise de um valor com uma determinada característica, por exemplo, começando com a letra 'M'. Agora as coisas ficam complicadas.
A única solução que eu encontrei até agora é colocar toda a sua consulta em uma subconsulta e construir manualmente a coluna adicional fora dela:
SELECT
countrylist.*,(SELECTTOP1 city
FROM locations
WHERE
country = countrylist.country
AND city like'M%')FROM(SELECT country FROM locations
GROUPBY country) countrylist
vai resultar em:
--country-- --city--
France Marseille
Poland NULL
Italy Milano
Ótima pergunta @aryaxt - você pode dizer que foi uma ótima pergunta porque você a perguntou há 5 anos e eu me deparei com ela hoje tentando encontrar a resposta!
Eu apenas tentei editar a resposta aceita para incluir isso, mas caso minha edição não consiga:
Se sua tabela não era tão grande e assumindo que sua chave primária era um número inteiro com auto-incremento, você poderia fazer algo assim:
SELECTtable.*FROMtable--be able to take out dupes laterLEFTJOIN(SELECT field, MAX(id)as id
FROMtableGROUPBY field
)as noDupes on noDupes.id =table.id
WHERE//this will result in only the last instance being seen
noDupes.id isnotNULL
No SQL Server, você pode usar as funções de janelas dense_rank e adicionais para obter todas as linhas E colunas com valores duplicados nas colunas especificadas. Aqui está um exemplo...
with t as(select col1 ='a', col2 ='b', col3 ='c', other ='r1'unionallselect col1 ='c', col2 ='b', col3 ='a', other ='r2'unionallselect col1 ='a', col2 ='b', col3 ='c', other ='r3'unionallselect col1 ='a', col2 ='b', col3 ='c', other ='r4'unionallselect col1 ='c', col2 ='b', col3 ='a', other ='r5'unionallselect col1 ='a', col2 ='a', col3 ='a', other ='r6'), tdr as(select*,
total_dr_rows = count(*)over(partitionby dr)from(select*,
dr = dense_rank()over(orderby col1, col2, col3),
dr_rn = row_number()over(partitionby col1, col2, col3 orderby other)from
t
) x
)select*from tdr where total_dr_rows >1
Isso leva uma contagem de linhas para cada combinação distinta de col1, col2 e col3.
Isso funcionou para mim !! Vale a pena notar que, se você estiver usando fetch_array (), precisará chamar cada linha por meio de um rótulo de índice, em vez de chamar implicitamente o nome da linha. Não há caracteres suficientes para escrever o exemplo que tenho: X desculpe!
Como mencionado na resposta aceite, iria trabalhar para a maioria das encarnações de SQL - apenas para MYSQL
Garrett Simpson
0
Encontrei isso em outro lugar aqui, mas esta é uma solução simples que funciona:
WITH cte AS/* Declaring a new table named 'cte' to be a clone of your table */(SELECT*, ROW_NUMBER()OVER(PARTITIONBY id ORDERBY val1 DESC)AS rn
FROM MyTable /* Selecting only unique values based on the "id" field */)SELECT*/* Here you can specify several columns to retrieve */FROM cte
WHERE rn =1
A cláusula GROUP BY deve corresponder aos campos selecionados. caso contrário, ele lançará um erro comofiled2 must appear in the GROUP BY clause or be used in an aggregate function
Viuu -a
-2
Basta incluir todos os seus campos na cláusula GROUP BY.
Isso não fará o trabalho. Você selecionou a coluna distinta na subconsulta, mas a cláusula where obtém todas as colunas com esse valor. Portanto, a consulta é tão boa quanto escrever 'select * from table', a menos que a coluna 'field' seja uma coluna única. Nesse caso, a distinção nessa coluna não é necessária.
Ankur-m
-3
SELECT DISTINCT FIELD1, FIELD2, FIELD3 FROM TABLE1 funcionará se os valores de todas as três colunas forem exclusivos na tabela.
Se, por exemplo, você tiver vários valores idênticos para o primeiro nome, mas o sobrenome e outras informações nas colunas selecionadas forem diferentes, o registro será incluído no conjunto de resultados.
SELECT DISTINCT * FROM table
funciona para você?distinct
por definição. Se você está tentando apenas selecionar,DISTINCT field1
mas de alguma forma retornar todas as outras colunas, o que deve acontecer com as colunas que possuem mais de um valor para umfield1
valor específico ? Você precisaria usarGROUP BY
e algum tipo de agregação nas outras colunas, por exemplo.Respostas:
Você está procurando um grupo por:
Ocasionalmente, pode ser escrito com uma declaração distinta:
Na maioria das plataformas, no entanto, nenhuma das opções acima funcionará porque o comportamento nas outras colunas não é especificado. (O primeiro funciona no MySQL, se é isso que você está usando.)
Você pode buscar os campos distintos e escolher uma única linha arbitrária a cada vez.
Em algumas plataformas (por exemplo, PostgreSQL, Oracle, T-SQL), isso pode ser feito diretamente usando as funções da janela:
Em outros (MySQL, SQLite), você precisará escrever subconsultas que farão com que você junte toda a tabela consigo ( exemplo ), por isso não é recomendado.
fonte
The ranking function "row_number" must have an ORDER BY clause
. Precisamos adicionar ordem por cláusula após partição por campo1. Portanto, a consulta correta será:select * from ( select *, row_number() over (partition by field1 order by orderbyFieldName) as row_number from table ) as rows where row_number = 1
GROUP BY
select *, row_number() over (partition by field1 order by field2) as row_number from table
. Você tem que usar explicitamente nome da tabela / alias na consulta seleçãoselect **table**.*, row_number() over (partition by field1 order by field2) as row_number from table
select distinct on (field1) * from table
; trabalha também no PostgreSQLA partir da formulação da sua pergunta, entendo que você deseja selecionar os valores distintos para um determinado campo e para cada um desses valores ter todos os outros valores da coluna na mesma linha listados. A maioria dos DBMSs não permitirá isso com nem
DISTINCT
nemGROUP BY
porque o resultado não é determinado.Pense assim: se o seu
field1
ocorrer mais de uma vez, qual o valor defield2
será listado (dado que você tem o mesmo valorfield1
em duas linhas, mas dois valores distintosfield2
nessas duas linhas).No entanto, você pode usar funções agregadas (explicitamente para todos os campos que deseja que sejam mostrados) e usar um em
GROUP BY
vez deDISTINCT
:fonte
SELECT field1, MIN(field2), MIN(field3), MIN(field4), .... FROM table GROUP BY field1
, e os campos 2, 3, 4 ,,, não precisam ser números inteiros (ou outros dígitos), eles também podem ser campos de caracteressum(cast(COL as int)) > 0
Se entendi seu problema corretamente, é semelhante ao que acabei de ter. Você deseja limitar a usabilidade do DISTINCT a um campo especificado, em vez de aplicá-lo a todos os dados.
Se você usar GROUP BY sem uma função agregada, em qualquer campo que você GROUP BY será seu arquivo DISTINCT.
Se você fizer sua consulta:
Ele mostrará todos os seus resultados com base em uma única instância do campo1.
Por exemplo, se você tiver uma tabela com nome, endereço e cidade. Uma única pessoa tem vários endereços registrados, mas você só quer um único endereço para a pessoa, pode consultar da seguinte maneira:
O resultado será que apenas uma instância desse nome aparecerá com seu endereço e a outra será omitida da tabela resultante. Cuidado: se seus arquivos tiverem valores atômicos como firstName, lastName, você deseja agrupar por ambos.
porque se duas pessoas tiverem o mesmo sobrenome e você agrupar apenas por sobrenome, uma dessas pessoas será omitida dos resultados. Você precisa manter essas coisas em consideração. Espero que isto ajude.
fonte
fonte
C
alias
quando ele pode funcionar sem ele? na linhaFROM dbo.TABLE AS C
Essa é uma pergunta muito boa. Eu já li algumas respostas úteis aqui, mas provavelmente posso adicionar uma explicação mais precisa.
Reduzir o número de resultados da consulta com uma instrução GROUP BY é fácil, desde que você não consulte informações adicionais. Vamos supor que você tenha a seguinte tabela 'locais'.
Agora a consulta
vai resultar em:
No entanto, a seguinte consulta
... gera um erro no MS SQL, porque como seu computador pode saber qual das três cidades francesas "Lyon", "Paris" ou "Marselha" você deseja ler no campo à direita de "França"?
Para corrigir a segunda consulta, você deve adicionar essas informações. Uma maneira de fazer isso é usar as funções MAX () ou MIN (), selecionando o valor maior ou menor entre todos os candidatos. MAX () e MIN () não são apenas aplicáveis aos valores numéricos, mas também comparam a ordem alfabética dos valores das strings.
vai resultar em:
ou:
vai resultar em:
Essas funções são uma boa solução, desde que você esteja bem ao selecionar seu valor nas extremidades da ordem alfabética (ou numérica). Mas e se não for esse o caso? Vamos supor que você precise de um valor com uma determinada característica, por exemplo, começando com a letra 'M'. Agora as coisas ficam complicadas.
A única solução que eu encontrei até agora é colocar toda a sua consulta em uma subconsulta e construir manualmente a coluna adicional fora dela:
vai resultar em:
fonte
Ótima pergunta @aryaxt - você pode dizer que foi uma ótima pergunta porque você a perguntou há 5 anos e eu me deparei com ela hoje tentando encontrar a resposta!
Eu apenas tentei editar a resposta aceita para incluir isso, mas caso minha edição não consiga:
Se sua tabela não era tão grande e assumindo que sua chave primária era um número inteiro com auto-incremento, você poderia fazer algo assim:
fonte
Tentar
fonte
Você pode fazer isso com uma
WITH
cláusula.Por exemplo:
Isso também permite selecionar apenas as linhas selecionadas na
WITH
consulta de cláusulas.fonte
No SQL Server, você pode usar as funções de janelas dense_rank e adicionais para obter todas as linhas E colunas com valores duplicados nas colunas especificadas. Aqui está um exemplo...
Isso leva uma contagem de linhas para cada combinação distinta de col1, col2 e col3.
fonte
fonte
em
ORDER BY
Acabei de colocar exemplo aqui, você também pode adicionar o campo ID nestefonte
Encontrei isso em outro lugar aqui, mas esta é uma solução simples que funciona:
fonte
Adicione GROUP BY ao campo que você deseja verificar se há duplicatas. Sua consulta pode parecer
campo1 será verificado para excluir registros duplicados
ou você pode consultar como
registros duplicados do campo1 são excluídos de SELECT
fonte
filed2 must appear in the GROUP BY clause or be used in an aggregate function
Basta incluir todos os seus campos na cláusula GROUP BY.
fonte
Isso pode ser feito por consulta interna
fonte
fonte
SELECT DISTINCT FIELD1, FIELD2, FIELD3 FROM TABLE1 funcionará se os valores de todas as três colunas forem exclusivos na tabela.
Se, por exemplo, você tiver vários valores idênticos para o primeiro nome, mas o sobrenome e outras informações nas colunas selecionadas forem diferentes, o registro será incluído no conjunto de resultados.
fonte
Eu sugeriria usar
dessa forma, se você tiver o mesmo valor no campo1 em várias linhas, todos os registros serão retornados.
fonte
SELECT * FROM table;
. Ainda mais É lento.