source

SQL 서버에서 중복 행 찾기

itover 2023. 4. 7. 21:12
반응형

SQL 서버에서 중복 행 찾기

조직의 SQL Server 데이터베이스가 있으며 중복된 행이 많습니다.select 문을 실행하여 이러한 모든 항목과 DUP 수를 가져오고 각 조직과 관련된 ID도 반환합니다.

다음과 같은 문장이 있습니다.

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  

그 이유는 이들 조직에 링크하는 별도의 사용자 테이블이 있기 때문에 이들을 통합하고 싶기 때문입니다(따라서 dupe를 삭제하여 사용자가 dupe org가 아닌 동일한 조직에 링크할 수 있도록 합니다).하지만 저는 아무것도 망치지 않도록 수동으로 파트를 하고 싶습니다만, 그래도 모든 dupe org의 ID를 반환하는 스테이트먼트가 필요합니다.그래서 사용자 목록을 살펴볼 수 있습니다.

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

다음 쿼리를 실행하여 중복된 항목을 찾을 수 있습니다.max(id)해당 행을 삭제합니다.

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

하지만 이 쿼리를 몇 번 실행해야 합니다.

다음과 같이 할 수 있습니다.

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

삭제할 수 있는 레코드만 반환할 경우(각 레코드를 1개 남김) 다음을 사용할 수 있습니다.

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

당신은 이것을 시도해 볼 수 있습니다, 그것은 당신에게 최선입니다.

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

정답으로 표시된 솔루션은 효과가 없었지만, 다음과 같은 답변이 매우 효과적이었습니다.MySql에서 중복 행 목록 가져오기

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

중복을 삭제하는 경우:

WITH CTE AS(
   SELECT orgName,id,
       RN = ROW_NUMBER()OVER(PARTITION BY orgName ORDER BY Id)
   FROM organizations
)
DELETE FROM CTE WHERE RN > 1
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 
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은 중복된 레코드로 삭제될 수 있습니다.

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

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

선택에는 몇 가지 방법이 있습니다.duplicate rows.

예를 들어, 먼저 이 표를 검토하십시오.

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

첫 번째 해결책:

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

Secound 솔루션: 사용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

및 모든 솔루션의 끝은 이 솔루션을 종료합니다.

DROP TABLE #Employee

당신이 원하는 걸 알 것 같아요 대답을 섞어야 했고 그가 원하는 해결책을 찾은 것 같아요

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

max id를 지정하면 dublicate의 ID와 그가 요구한 원본의 ID를 얻을 수 있습니다.

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)

이런 형태로 발표되는 유일한 슬픈 일

id , name , dubid , name

그래도 도움이 되길 바란다

두 개의 열이 있는 표 'Student'가 있다고 가정합니다.

  • student_id int
  • student_name varchar

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

중복된 레코드가 표시됩니다.다음 쿼리를 사용합니다.

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

테이블에서 중복된 레코드를 가져올 수 있는 더 좋은 옵션이 있어요

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

위 쿼리의 결과는 고유한 학생 ID와 중복 발생 횟수를 가진 중복된 이름을 모두 표시합니다.

SQL 결과를 보려면 여기를 클릭하십시오.

 /*To get duplicate data in table */

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

중복 행을 찾기 위해 두 가지 방법을 사용합니다.첫 번째 방법은 by와 have를 사용하는 방법 중 가장 유명합니다.두 번째 방법은 CTE - Common Table Expression을 사용하는 것입니다.

@RedFilter에서 언급했듯이 이 방법도 맞습니다.CTE 방법도 도움이 되는 경우가 많습니다.

WITH TempOrg (orgName,RepeatCount)
AS
(
SELECT orgName,ROW_NUMBER() OVER(PARTITION by orgName ORDER BY orgName) 
AS RepeatCount
FROM dbo.organizations
)
select t.*,e.id from organizations   e
inner join TempOrg t on t.orgName= e.orgName
where t.RepeatCount>1

위의 예에서는 ROW_NUMBER와 PARTITION BY를 사용하여 반복 발생을 찾아 결과를 수집했습니다.그런 다음 where 구를 적용하여 반복 횟수가 1 이상인 행만 선택합니다.모든 결과는 CTE 테이블을 수집하여 Organizations 테이블과 결합됩니다.

출처 : CodoBee.

해라

SELECT orgName, id, count(*) as dupes
FROM organizations
GROUP BY orgName, id
HAVING count(*) > 1;

언급URL : https://stackoverflow.com/questions/2112618/finding-duplicate-rows-in-sql-server

반응형