sql-server 중복제거 - SQL Server에서 중복 행 찾기




개수 데이터 (14)

조직의 SQL Server 데이터베이스가 있고 많은 중복 행이 있습니다. select 문을 실행하여이 모든 내용과 중복 된 내용을 가져오고 각 조직과 관련된 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 

그러나 나는 또한 그들 ID를 얻고 싶습니다. 이 일을 할 수있는 방법이 있습니까? 어쩌면

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

그 이유는이 조직에 링크 된 별도의 사용자 테이블이 있기 때문입니다. 따라서이를 통합하여 사용자가 중복 된 조직을 제거하므로 사용자가 중복 조직 대신 동일한 조직에 연결됩니다. 그러나 나는 수동으로 부품을 원하므로 아무 것도 망치지는 않겠지 만 모든 사기 조직의 ID를 반환하는 진술이 필요하므로 사용자 목록을 검토 할 수 있습니다.


Answers

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

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

너는 이것을 시도 할 수있다, 너를 위해 최상이다.

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

우리가 2 개의 칼럼을 가진 table '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 * 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 

올바른 것으로 표시된 솔루션은 나에게 효과가 없었지만이 답변은 훌륭했습니다. MySql에서 중복 행 목록 가져 오기

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

Select * from (Select orgName,id,
ROW_NUMBER() OVER(Partition By OrgName ORDER by id DESC) Rownum
From organizations )tbl Where Rownum>1

따라서 rowum> 1 인 레코드는 테이블의 중복 레코드가됩니다. 'Partition By'레코드에 의해 첫 번째 그룹을 만들고 일련 번호를 부여하여 일련 번호를 매 깁니다. 따라서 rownum> 1은 삭제 될 수있는 중복 레코드가됩니다.


duplicate rows 선택을위한 여러 가지 방법이 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

초창 솔루션 : 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

최대 이드를 가짐으로써 당신에게 도둑질의 이드와 그가 요청한 원래의 것의 하나를 줄 것입니다.

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

여전히 도움이되기를 바란다.


테이블에 중복 레코드를 가져 오는 더 좋은 옵션이 있습니다.

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의 결과를 보려면 여기를 클릭하십시오.


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

중복 된 항목을 삭제하려면 다음을 수행하십시오.

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 orgName, id, count(*) as dupes
FROM organizations
GROUP BY orgName, id
HAVING count(*) > 1;

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

참고 : 이 대답은 SQL Server 2005에 대한 것입니다. SQL Server 2008 이상에서는 다른 대답에서 볼 수있는 훨씬 좋은 방법이 있습니다.

SELECT UNION ALL과 함께 INSERT를 사용할 수 있습니다.

INSERT INTO MyTable  (FirstCol, SecondCol)
    SELECT  'First' ,1
    UNION ALL
SELECT  'Second' ,2
    UNION ALL
SELECT  'Third' ,3
...

작은 데이터 세트에 대해서만, 귀하의 4 레코드에 대해 잘해야합니다.





sql sql-server duplicates