Поиск дублирующихся строк в SQL Server - PullRequest
216 голосов
/ 21 января 2010

У меня есть база данных организаций SQL Server, и есть много повторяющихся строк. Я хочу выполнить оператор select, чтобы получить все эти данные и количество дубликатов, а также вернуть идентификаторы, связанные с каждой организацией.

утверждение типа:

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

Вернет что-то вроде

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

Но я также хотел бы получить их удостоверения личности. Есть какой-либо способ сделать это? Может быть, как

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

Причина в том, что существует также отдельная таблица пользователей, которые ссылаются на эти организации, и я хотел бы объединить их (поэтому удалите дубликаты, чтобы пользователи ссылались на одну и ту же организацию, а не на двойные организации). Но я бы хотел расставить детали вручную, чтобы ничего не напортачить, но мне все равно нужен оператор, возвращающий идентификаторы всех двойных организаций, чтобы я мог просмотреть список пользователей.

Ответы [ 17 ]

304 голосов
/ 21 января 2010
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
88 голосов
/ 21 января 2010

Вы можете выполнить следующий запрос и найти дубликаты с помощью max(id) и удалить эти строки.

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

Но вам придется выполнить этот запрос несколько раз.

31 голосов
/ 21 января 2010

Вы можете сделать это так:

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

Если вы хотите вернуть только те записи, которые можно удалить (оставив одну из каждой), вы можете использовать:

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

Редактировать: SQL Server 2000 не имеет функции ROW_NUMBER (). Вместо этого вы можете использовать:

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
9 голосов
/ 21 мая 2013

Решение, помеченное как правильное, у меня не сработало, но я нашел ответ, который работал просто замечательно: Получить список повторяющихся строк в MySql

SELECT n1.* 
FROM myTable n1
INNER JOIN myTable n2 
ON n2.repeatedCol = n1.repeatedCol
WHERE n1.id <> n2.id
8 голосов
/ 07 ноября 2013

Вы можете попробовать это, это лучше для вас

 WITH CTE AS
    (
    SELECT *,RN=ROW_NUMBER() OVER (PARTITION BY orgName ORDER BY orgName DESC) FROM organizations 
    )
    select * from CTE where RN>1
    go
4 голосов
/ 18 ноября 2016
select * from [Employees]

Для поиска дубликата записи 1) Использование 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) Используя GroupBy

select Name,EmailId,COUNT(name) as Duplicate from  [Employees] group by Name,EmailId 
4 голосов
/ 17 июня 2016

Если вы хотите удалить дубликаты:

WITH CTE AS(
   SELECT orgName,id,
       RN = ROW_NUMBER()OVER(PARTITION BY orgName ORDER BY Id)
   FROM organizations
)
DELETE FROM CTE WHERE RN > 1
3 голосов
/ 10 марта 2015
Select * from (Select orgName,id,
ROW_NUMBER() OVER(Partition By OrgName ORDER by id DESC) Rownum
From organizations )tbl Where Rownum>1

Таким образом, записи с rowum> 1 будут дублировать записи в вашей таблице. «Разделите» на первую группу по записям, а затем сериализуйте их, дав им серийные номера. Таким образом, rownum> 1 будет дублировать записи, которые могут быть удалены как таковые.

2 голосов
/ 15 сентября 2015
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 голосов
/ 17 марта 2015
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

...