Extraire uniquement le premier de l’unité d’enregistrement où la valeur de la colonne spécifiée est dupliquée
Normalement, lorsqu’on extrait un seul enregistrement en double, la première chose qui vient à l’esprit est distinct
je pense,
distinct
ne vous permet pas de spécifier une colonne en double et une autre colonne que vous souhaitez récupérer en même temps.
De plus,distinct
ne répond pas à cette exigence car il inclut des enregistrements non dupliqués dans l’extraction.
Je ne pense pas que vous puissiez comprendre ce que vous voulez faire avec le titre seul, alors prenons l’exemple d’un exemple d’enregistrement. Ce que je veux faire, c’est le résultat d’extraction suivant.
Nom de l’ID | |
---|---|
1 | Nom 1 |
2 | Nom 2 |
3 | Nom 3 |
3 | Nom 3@example.com |
4 | Nom 4 Nom 4@example.com |
4 | Nom 4@example.com |
4 | Nom 4@example.com |
Obtenez-le comme suit :
Nom de l’ID | |
---|---|
3 | Nom 3@example.com |
4 | Nom 4@example.com |
Les ID 1 et 2 ne sont pas inclus, car ils ne sont pas des doublons. Les ID 3 et 4 sont des doublons, de sorte que l’un d’entre eux est récupéré. Cependant, cette fois-ci, nous n’obtiendrons pas le premier enregistrement de l’ordre de stockage de la base de données. En outre, supposons que vous souhaitiez que la première ligne du nom soit classée par ordre de priorité dans les conditions suivantes : « Le nom contient une marque @ » et « Le nom comporte un petit nombre de caractères ».
La condition ci-dessus peut être obtenue avec le SQL suivant. Cependant, nous utilisons des sous-requêtes et n’avons pas vérifié les performances.
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)
)
Les lignes en double sont having
vérifiées à l’aide de et count
. group by
La colonne clé à vérifier de l’extérieur, ici ID
la colonne est where
réduite par .
L’ordre de priorité pour l’extraction de la première ligne est order by
spécifié par . charindex
Ici, et len
vérifiez s’il contient le caractère spécifié et la longueur de la chaîne.
top
Tout ce que vous avez à faire est d’obtenir la première ligne de chaque enregistrement en double dans .
À l’origine, ce n’est pas grave, mais s’il y a deux enregistrements ou plus avec exactement la même valeur, comme « ID : 4, Nom : Nom 4@example.com », vous obtiendrez inévitablement deux enregistrements.
row_number
Par conséquent, il est ajouté de manière à pouvoir être identifié pour chaque ligne avec , de sorte qu’un seul enregistrement avec exactement la même valeur puisse être récupéré.
Si l’on sait que le même enregistrement n’existe pas, je row_number
pense qu’il serait préférable de vérifier les valeurs des enregistrements existants sans ajouter .
S’il y a plusieurs clés à vérifier pour les doublons, vous pouvez augmenter le nombre de colonnes de clés pour chacune. Prenons l’exemple de l’enregistrement suivant : Les colonnes à vérifier pour les doublons sont « ID1 » et « ID2 ».
ID1 | ID2 | Nom |
---|---|---|
1 | 1 | Nom 1 |
2 | 1 | Nom 2 |
3 | 1 | Nom 31 |
3 | 2 | Nom 32 |
4 | 1 | Nom41 |
4 | 2 | Nom42 |
4 | 2 | Nom 4@example.com |
5 | 1 | Nom 555@example.com |
5 | 1 | Nom 55@example.com |
5 | 2 | Nom 5@example.com |
6 | 1 | Nom 6 |
6 | 1 | Nom 66@example.com |
6 | 2 | Nom 6 |
6 | 2 | Nom 6 |
Le résultat de l’acquisition est le suivant.
ID1 | ID2 | Nom |
---|---|---|
4 | 2 | Nom 4@example.com |
5 | 1 | Nom 55@example.com |
6 | 1 | Nom 66@example.com |
6 | 2 | Nom 6 |
Le code SQL se présente comme suit : Vous pouvez simplement augmenter la partie où la colonne clé a été spécifiée.
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)
)