web-dev-qa-db-fra.com

Recherche de lignes en double dans SQL Server

J'ai une base de données d'organisations SQL Server et il y a beaucoup de lignes en double. Je souhaite exécuter une instruction select pour récupérer tout cela et la quantité de dupes, mais aussi renvoyer les identifiants associés à chaque organisation.

Une déclaration comme:

SELECT     orgName, COUNT(*) AS dupes  
FROM         organizations  
GROUP BY orgName  
HAVING      (COUNT(*) > 1)

Retournera quelque chose comme

orgName        | dupes  
ABC Corp       | 7  
Foo Federation | 5  
Widget Company | 2 

Mais j'aimerais aussi en saisir les identifiants. Est-ce qu'il y a un moyen de faire ça? Peut-être comme un

orgName        | dupeCount | id  
ABC Corp       | 1         | 34  
ABC Corp       | 2         | 5  
...  
Widget Company | 1         | 10  
Widget Company | 2         | 2  

La raison en est qu’il existe également un tableau séparé des utilisateurs qui sont liés à ces organisations, et je voudrais les unifier (par conséquent, supprimez les dupes afin que les utilisateurs se connectent à la même organisation plutôt que des organisations de dupe). Mais je voudrais une partie manuellement afin de ne rien foirer, mais il me faudrait quand même une déclaration renvoyant les identifiants de toutes les organisations dupliquées pour pouvoir consulter la liste des utilisateurs.

216
xtine
select o.orgName, oc.dupeCount, o.id
from organizations o
inner join (
    SELECT orgName, COUNT(*) AS dupeCount
    FROM organizations
    GROUP BY orgName
    HAVING COUNT(*) > 1
) oc on o.orgName = oc.orgName
305
RedFilter

Vous pouvez exécuter la requête suivante et rechercher les doublons avec max(id) et supprimer ces lignes.

SELECT orgName, COUNT(*), Max(ID) AS dupes 
FROM organizations 
GROUP BY orgName 
HAVING (COUNT(*) > 1)

Mais vous devrez exécuter cette requête plusieurs fois.

88
Aykut Akıncı

Vous pouvez le faire comme ça:

SELECT
    o.id, o.orgName, d.intCount
FROM (
     SELECT orgName, COUNT(*) as intCount
     FROM organizations
     GROUP BY orgName
     HAVING COUNT(*) > 1
) AS d
    INNER JOIN organizations o ON o.orgName = d.orgName

Si vous souhaitez ne renvoyer que les enregistrements pouvant être supprimés (en en laissant un de chaque), vous pouvez utiliser:

SELECT
    id, orgName
FROM (
     SELECT 
         orgName, id,
         ROW_NUMBER() OVER (PARTITION BY orgName ORDER BY id) AS intRow
     FROM organizations
) AS d
WHERE intRow != 1

Edit: SQL Server 2000 n'a pas la fonction ROW_NUMBER (). Au lieu de cela, vous pouvez utiliser:

SELECT
    o.id, o.orgName, d.intCount
FROM (
     SELECT orgName, COUNT(*) as intCount, MIN(id) AS minId
     FROM organizations
     GROUP BY orgName
     HAVING COUNT(*) > 1
) AS d
    INNER JOIN organizations o ON o.orgName = d.orgName
WHERE d.minId != o.id
31
Paul

La solution marquée comme correcte ne fonctionnait pas pour moi, mais j'ai trouvé cette réponse qui fonctionnait à merveille: obtenir la liste des lignes en double dans MySql

SELECT n1.* 
FROM myTable n1
INNER JOIN myTable n2 
ON n2.repeatedCol = n1.repeatedCol
WHERE n1.id <> n2.id
9
ecairol

Tu peux essayer ça, c'est mieux pour toi

 WITH CTE AS
    (
    SELECT *,RN=ROW_NUMBER() OVER (PARTITION BY orgName ORDER BY orgName DESC) FROM organizations 
    )
    select * from CTE where RN>1
    go
9
code save
select * from [Employees]

Pour trouver des doublons Enregistrement 1) Utilisation de CTE

with mycte
as
(
select Name,EmailId,ROW_NUMBER() over(partition by Name,EmailId order by id) as Duplicate from [Employees]
)
select * from mycte

2) En utilisant GroupBy

select Name,EmailId,COUNT(name) as Duplicate from  [Employees] group by Name,EmailId 
5
Debendra Dash

Si vous souhaitez supprimer les doublons:

WITH CTE AS(
   SELECT orgName,id,
       RN = ROW_NUMBER()OVER(PARTITION BY orgName ORDER BY Id)
   FROM organizations
)
DELETE FROM CTE WHERE RN > 1
5
akd
Select * from (Select orgName,id,
ROW_NUMBER() OVER(Partition By OrgName ORDER by id DESC) Rownum
From organizations )tbl Where Rownum>1

Ainsi, les enregistrements avec rowum> 1 seront les enregistrements en double dans votre table. 'Partitionnez par' premier groupe par les enregistrements, puis sérialisez-les en leur donnant les numéros de série. Donc, rownum> 1 seront les enregistrements en double qui pourraient être supprimés en tant que tels.

3
Mike Clark
select column_name, count(column_name)
from table_name
group by column_name
having count (column_name) > 1;

Src: https://stackoverflow.com/a/59242/1465252

2
iCrazybest
select a.orgName,b.duplicate, a.id
from organizations a
inner join (
    SELECT orgName, COUNT(*) AS duplicate
    FROM organizations
    GROUP BY orgName
    HAVING COUNT(*) > 1
) b on o.orgName = oc.orgName
group by a.orgName,a.id
2
user5336758
select orgname, count(*) as dupes, id 
from organizations
where orgname in (
    select orgname
    from organizations
    group by orgname
    having (count(*) > 1)
)
group by orgname, id
1
Jordão

Vous avez plusieurs possibilités pour sélectionner duplicate rows.

pour mes solutions, considérons d'abord ce tableau par exemple

CREATE TABLE #Employee
(
ID          INT,
FIRST_NAME  NVARCHAR(100),
LAST_NAME   NVARCHAR(300)
)

INSERT INTO #Employee VALUES ( 1, 'Ardalan', 'Shahgholi' );
INSERT INTO #Employee VALUES ( 2, 'name1', 'lname1' );
INSERT INTO #Employee VALUES ( 3, 'name2', 'lname2' );
INSERT INTO #Employee VALUES ( 2, 'name1', 'lname1' );
INSERT INTO #Employee VALUES ( 3, 'name2', 'lname2' );
INSERT INTO #Employee VALUES ( 4, 'name3', 'lname3' );

Première solution:

SELECT DISTINCT *
FROM   #Employee;

WITH #DeleteEmployee AS (
                     SELECT ROW_NUMBER()
                            OVER(PARTITION BY ID, First_Name, Last_Name ORDER BY ID) AS
                            RNUM
                     FROM   #Employee
                 )

SELECT *
FROM   #DeleteEmployee
WHERE  RNUM > 1

SELECT DISTINCT *
FROM   #Employee

Solution secondaire: Utilisez le champ identity

SELECT DISTINCT *
FROM   #Employee;

ALTER TABLE #Employee ADD UNIQ_ID INT IDENTITY(1, 1)

SELECT *
FROM   #Employee
WHERE  UNIQ_ID < (
    SELECT MAX(UNIQ_ID)
    FROM   #Employee a2
    WHERE  #Employee.ID = a2.ID
           AND #Employee.FIRST_NAME = a2.FIRST_NAME
           AND #Employee.LAST_NAME = a2.LAST_NAME
)

ALTER TABLE #Employee DROP COLUMN UNIQ_ID

SELECT DISTINCT *
FROM   #Employee

et fin de toute solution utiliser cette commande

DROP TABLE #Employee
1

Supposons que nous ayons la table 'Student' avec 2 colonnes:

  • student_id int
  • student_name varchar

    Records:
    +------------+---------------------+
    | student_id | student_name        |
    +------------+---------------------+
    |        101 | usman               |
    |        101 | usman               |
    |        101 | usman               |
    |        102 | usmanyaqoob         |
    |        103 | muhammadusmanyaqoob |
    |        103 | muhammadusmanyaqoob |
    +------------+---------------------+
    

Maintenant, nous voulons voir les enregistrements en double Utilisez cette requête:

select student_name,student_id ,count(*) c from student group by student_id,student_name having c>1;
+---------------------+------------+---+
| student_name        | student_id | c |
+---------------------+------------+---+
| usman               |        101 | 3 |
| muhammadusmanyaqoob |        103 | 2 |
+---------------------+------------+---+
0
Usman Yaqoob

J'ai une meilleure option pour obtenir les enregistrements en double dans une table

SELECT x.studid, y.stdname, y.dupecount
FROM student AS x INNER JOIN
(SELECT a.stdname, COUNT(*) AS dupecount
FROM student AS a INNER JOIN
studmisc AS b ON a.studid = b.studid
WHERE (a.studid LIKE '2018%') AND (b.studstatus = 4)
GROUP BY a.stdname
HAVING (COUNT(*) > 1)) AS y ON x.stdname = y.stdname INNER JOIN
studmisc AS z ON x.studid = z.studid
WHERE (x.studid LIKE '2018%') AND (z.studstatus = 4)
ORDER BY x.stdname

Le résultat de la requête ci-dessus montre tous les noms en double avec des ID d'étudiant uniques et le nombre d'occurrences en double.

Cliquez ici pour voir le résultat du SQL

0
SoftIdea
 /*To get duplicate data in table */

 SELECT COUNT(EmpCode),EmpCode FROM tbl_Employees WHERE Status=1 
  GROUP BY EmpCode HAVING COUNT(EmpCode) > 1
0
JIYAUL MUSTAPHA

je pense que je sais ce dont vous avez besoin, je devais mélanger les réponses et je pense avoir la solution qu'il cherchait:

select o.id,o.orgName, oc.dupeCount, oc.id,oc.orgName
from organizations o
inner join (
    SELECT MAX(id) as id, orgName, COUNT(*) AS dupeCount
    FROM organizations
    GROUP BY orgName
    HAVING COUNT(*) > 1
) oc on o.orgName = oc.orgName

avoir le max id vous donnera l'identifiant du duplicate et celui de l'original qui correspond à ce qu'il a demandé:

id org name , dublicate count (missing out in this case) 
id doublicate org name , doub count (missing out again because does not help in this case)

seule chose triste que vous obtenez mis dans cette forme

id , name , dubid , name

espérons que cela aide toujours

0
Arthur Kielbasa