Extraia apenas o primeiro da unidade de registro em que o valor da coluna especificada é duplicado
Normalmente, ao extrair apenas um registro duplicado, a primeira coisa que vem à mente é distinct
que eu penso,
distinct
não permite que você especifique uma coluna duplicada e outra coluna que você deseja recuperar ao mesmo tempo.
Além disso,distinct
não corresponde a esse requisito porque inclui registros não duplicados na extração.
Eu não acho que você pode entender o que você quer fazer apenas com o título, então vamos usar um registro de amostra como exemplo. O que eu quero fazer é o seguinte resultado de extração.
Nome | do ID |
---|---|
1 | Nome 1 |
2 | Nome 2 |
3 | Nome 3 |
3 | Nome 3@example.com |
4 | Nome 4 Nome 4@example.com |
4 | Nome 4@example.com |
4 | Nome 4@example.com |
Obtenha-o da seguinte maneira:
Nome | do ID |
---|---|
3 | Nome 3@example.com |
4 | Nome 4@example.com |
Os IDs 1 e 2 não são incluídos porque não são duplicados. Os IDs 3 e 4 são duplicados, portanto, um deles é recuperado. No entanto, desta vez, não obteremos o primeiro registro na ordem de armazenamento do banco de dados. Além disso, suponha que você queira a primeira linha do nome em ordem de prioridade sob as condições de que "Nome contém uma marca @" e "Nome tem um pequeno número de caracteres".
A condição acima pode ser obtida com o seguinte SQL. No entanto, estamos usando subconsultas e não verificamos o desempenho.
select
*
from
(select *, row_number() over(order by ID asc) as RowNum from SampleTable) tableMain
where tableMain.RowNum =
(
select
top(1) RowNum
from
(select *, row_number() over(order by ID asc) as RowNum from SampleTable) tableSub
where
tableMain.ID = tableSub.ID
and exists (
select
*
from
SampleTable
where
tableSub.ID = ID
having
count(*) >= 2
)
order by
case when charindex(N'@', Name) >= 1 then 0 else 1 end, len(Name)
)
As linhas duplicadas são having
verificadas com e count
. group by
A coluna de chave a ser verificada de fora, aqui ID
a coluna é where
reduzida por .
A ordem de precedência para recuperar a primeira linha é order by
especificada por . charindex
Aqui, e len
verifique se ele contém o caractere especificado e o comprimento da string.
top
Tudo o que você precisa fazer é obter a primeira linha de cada registro duplicado em .
Originalmente, isso é bom, mas se houver dois ou mais registros com exatamente o mesmo valor, como "ID: 4, Nome: Nome 4@example.com", você inevitavelmente obterá dois registros.
row_number
Portanto, ele é anexado para que possa ser identificado para cada linha com , para que apenas um registro com exatamente o mesmo valor possa ser recuperado.
Se for sabido que exatamente o mesmo registro não existe, row_number
acho que seria melhor verificar os valores dos registros existentes sem anexar .
Se houver várias chaves a serem verificadas quanto a duplicatas, você poderá aumentar o número de colunas de chave para cada uma. Por exemplo, considere o seguinte registro: As colunas a serem verificadas quanto a duplicatas são "ID1" e "ID2".
ID1 | Nome ID2 | |
---|---|---|
1 | 1 | Nome 1 |
2 | 1 | Nome 2 |
3 | 1 | Nome 31 |
3 | 2 | Nome 32 |
4 | 1 | Nome41 |
4 | 2 | Nome42 |
4 | 2 | Nome 4@example.com |
5 | 1 | Nome 555@example.com |
5 | 1 | Nome 55@example.com |
5 | 2 | Nome 5@example.com |
6 | 1 | Nome 6 |
6 | 1 | Nome 66@example.com |
6 | 2 | Nome 6 |
6 | 2 | Nome 6 |
O resultado da aquisição é o seguinte.
ID1 | Nome ID2 | |
---|---|---|
4 | 2 | Nome 4@example.com |
5 | 1 | Nome 55@example.com |
6 | 1 | Nome 66@example.com |
6 | 2 | Nome 6 |
O SQL tem esta aparência: Você pode simplesmente aumentar a parte em que a coluna de chave foi especificada.
select
*
from
(select *, row_number() over(order by ID1 asc, ID2 asc) as RowNum from SampleTable) tableMain
where tableMain.RowNum =
(
select
top(1) RowNum
from
(select *, row_number() over(order by ID1 asc, ID2 asc) as RowNum from SampleTable) tableSub
where
tableMain.ID1 = tableSub.ID1
and tableMain.ID2 = tableSub.ID2
and exists (
select
*
from
SampleTable
where
tableSub.ID1 = ID1
and tableSub.ID2 = ID2
having
count(*) >= 2
)
order by
case when charindex(N'@', Name) >= 1 then 0 else 1 end, len(Name)
)