Extraire uniquement le premier de l’unité d’enregistrement où la valeur de la colonne spécifiée est dupliquée

Page mise à jour :
Date de création de la page :

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)
)