programing

SQL 테이블에서 중복 값 찾기

elseif 2023. 4. 9. 21:07

SQL 테이블에서 중복 값 찾기

하나의 필드와 중복되는 항목을 쉽게 찾을 수 있습니다.

SELECT email, COUNT(email) 
FROM users
GROUP BY email
HAVING COUNT(email) > 1

그래서 만약 우리가 자리가 있다면

ID   NAME   EMAIL
1    John   asd@asd.com
2    Sam    asd@asd.com
3    Tom    asd@asd.com
4    Bob    bob@asd.com
5    Tom    asd@asd.com

, Tom이 . 이 는 모두 있기 때문입니다. 왜냐하면 그들은 모두 같은 것을 가지고 있기 때문이다.email.

제가 은 같은 해서 받는 입니다.email ... name.

즉, "Tom"과 "Tom"을 원합니다.

잘못해서 중복 삽입을 했습니다.name ★★★★★★★★★★★★★★★★★」email가치.중복된 파일을 삭제/변경해야 하므로 먼저 찾아야 합니다.

SELECT
    name, email, COUNT(*)
FROM
    users
GROUP BY
    name, email
HAVING 
    COUNT(*) > 1

두 개의 열을 그룹화하기만 하면 됩니다.

참고: 이전 ANSI 표준은 GROUP BY에 모든 비집약 열을 포함하도록 되어 있지만, 이는 "기능 의존성"이라는 개념으로 변경되었습니다.

관계형 데이터베이스 이론에서, 함수 의존성은 데이터베이스로부터의 관계에서 두 개의 속성 집합 사이의 제약입니다.즉, 함수 의존성은 관계에서 속성 간의 관계를 설명하는 제약 조건입니다.

지원이 일관되지 않음:

이것을 시험해 보세요.

declare @YourTable table (id int, name varchar(10), email varchar(50))

INSERT @YourTable VALUES (1,'John','John-email')
INSERT @YourTable VALUES (2,'John','John-email')
INSERT @YourTable VALUES (3,'fred','John-email')
INSERT @YourTable VALUES (4,'fred','fred-email')
INSERT @YourTable VALUES (5,'sam','sam-email')
INSERT @YourTable VALUES (6,'sam','sam-email')

SELECT
    name,email, COUNT(*) AS CountOf
    FROM @YourTable
    GROUP BY name,email
    HAVING COUNT(*)>1

출력:

name       email       CountOf
---------- ----------- -----------
John       John-email  2
sam        sam-email   2

(2 row(s) affected)

dups 의 ID 를 사용하는 경우는, 다음과 같이 합니다.

SELECT
    y.id,y.name,y.email
    FROM @YourTable y
        INNER JOIN (SELECT
                        name,email, COUNT(*) AS CountOf
                        FROM @YourTable
                        GROUP BY name,email
                        HAVING COUNT(*)>1
                    ) dt ON y.name=dt.name AND y.email=dt.email

출력:

id          name       email
----------- ---------- ------------
1           John       John-email
2           John       John-email
5           sam        sam-email
6           sam        sam-email

(4 row(s) affected)

중복된 시도 삭제:

DELETE d
    FROM @YourTable d
        INNER JOIN (SELECT
                        y.id,y.name,y.email,ROW_NUMBER() OVER(PARTITION BY y.name,y.email ORDER BY y.name,y.email,y.id) AS RowRank
                        FROM @YourTable y
                            INNER JOIN (SELECT
                                            name,email, COUNT(*) AS CountOf
                                            FROM @YourTable
                                            GROUP BY name,email
                                            HAVING COUNT(*)>1
                                        ) dt ON y.name=dt.name AND y.email=dt.email
                   ) dt2 ON d.id=dt2.id
        WHERE dt2.RowRank!=1
SELECT * FROM @YourTable

출력:

id          name       email
----------- ---------- --------------
1           John       John-email
3           fred       John-email
4           fred       fred-email
5           sam        sam-email

(4 row(s) affected)

이것을 시험해 보세요.

SELECT name, email
FROM users
GROUP BY name, email
HAVING ( COUNT(*) > 1 )

중복된 항목을 삭제할 경우 짝수/홀수 행을 3중 하위 선택 항목으로 찾는 것보다 훨씬 간단한 방법이 있습니다.

SELECT id, name, email 
FROM users u, users u2
WHERE u.name = u2.name AND u.email = u2.email AND u.id > u2.id

삭제 방법:

DELETE FROM users
WHERE id IN (
    SELECT id/*, name, email*/
    FROM users u, users u2
    WHERE u.name = u2.name AND u.email = u2.email AND u.id > u2.id
)

IMHO를 훨씬 쉽게 읽고 이해할 수 있습니다.

주의: 중복되는 각 항목은 1개만 삭제되므로 삭제되는 행이 없을 때까지 요청을 실행해야 합니다.

다른 답변과 달리 모든 열이 포함된 전체 레코드를 볼 수 있습니다.에서PARTITION BYrow_number 함수의 일부에서는 원하는 고유/불규칙 열을 선택합니다.

SELECT  *
FROM    (
 SELECT a.*
 ,      Row_Number() OVER (PARTITION BY Name, Age ORDER BY Name) AS r
 FROM   Customers AS a
)       AS b
WHERE   r > 1;

모든 필드가 포함된 모든 중복된 레코드를 선택하려면 다음과 같이 쓸 수 있습니다.

CREATE TABLE test (
        id      bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY
,       c1      integer
,       c2      text
,       d       date DEFAULT now()
,       v       text
);

INSERT INTO test (c1, c2, v) VALUES
(1, 'a', 'Select'),
(1, 'a', 'ALL'),
(1, 'a', 'multiple'),
(1, 'a', 'records'),
(2, 'b', 'in columns'),
(2, 'b', 'c1 and c2'),
(3, 'c', '.');
SELECT * FROM test ORDER BY 1;

SELECT  *
FROM    test
WHERE   (c1, c2) IN (
 SELECT c1, c2
 FROM   test
 GROUP  BY 1,2
 HAVING count(*) > 1
)
ORDER   BY 1;

포스트그리에서 테스트 완료SQL.

 SELECT name, email 
    FROM users
    WHERE email in
    (SELECT email FROM users
    GROUP BY email 
    HAVING COUNT(*)>1)

파티에는 조금 늦었지만 모든 중복된 ID를 찾을 수 있는 정말 멋진 해결 방법을 찾았습니다.

SELECT email, GROUP_CONCAT(id)
FROM   users
GROUP  BY email
HAVING COUNT(email) > 1;

그러면 각 복제 그룹에서 하나의 레코드를 제외한 모든 중복 레코드가 선택/삭제됩니다.따라서 삭제하면 모든 고유 레코드 + 중복된 각 그룹의 레코드 1개가 남습니다.

중복 선택:

SELECT *
FROM <table>
WHERE
    id NOT IN (
        SELECT MIN(id)
        FROM table
        GROUP BY <column1>, <column2>
);

중복 삭제:

DELETE FROM <table>
WHERE
    id NOT IN (
        SELECT MIN(id)
        FROM table
        GROUP BY <column1>, <column2>
);

대량의 레코드는 퍼포먼스 문제를 일으킬 수 있으므로 주의해 주십시오.

이 코드를 사용해 보세요.

WITH CTE AS

( SELECT Id, Name, Age, Comments, RN = ROW_NUMBER()OVER(PARTITION BY Name,Age ORDER BY ccn)
FROM ccnmaster )
select * from CTE 

Oracle을 사용하는 경우 다음과 같은 방법을 사용하는 것이 좋습니다.

create table my_users(id number, name varchar2(100), email varchar2(100));

insert into my_users values (1, 'John', 'asd@asd.com');
insert into my_users values (2, 'Sam', 'asd@asd.com');
insert into my_users values (3, 'Tom', 'asd@asd.com');
insert into my_users values (4, 'Bob', 'bob@asd.com');
insert into my_users values (5, 'Tom', 'asd@asd.com');

commit;

select *
  from my_users
 where rowid not in (select min(rowid) from my_users group by name, email);
select name, email
, case 
when ROW_NUMBER () over (partition by name, email order by name) > 1 then 'Yes'
else 'No'
end "duplicated ?"
from users

위의 모든 답변에서 이 질문은 매우 깔끔하게 답변되었습니다.그러나 가능한 모든 방법을 나열하고 싶습니다.이러한 방법을 이해하려면 다양한 방법을 사용할 수 있습니다.또한 SQL 개발자는 자신의 요구에 가장 적합한 솔루션 중 하나를 선택할 수 있습니다.이는 다양한 비즈니스 사용 사례를 접하거나 인터뷰에서도 자주 볼 수 있는 가장 일반적인 질문 중 하나이기 때문입니다.

샘플 데이터 생성

이 질문의 샘플 데이터만 설정하겠습니다.

Create table NewTable (id int, name varchar(10), email varchar(50))
INSERT  NewTable VALUES (1,'John','asd@asd.com')
INSERT  NewTable VALUES (2,'Sam','asd@asd.com')
INSERT  NewTable VALUES (3,'Tom','asd@asd.com')
INSERT  NewTable VALUES (4,'Bob','bob@asd.com')
INSERT  NewTable VALUES (5,'Tom','asd@asd.com')

여기에 이미지 설명 입력

1. 조항의 그룹화 사용

SELECT
    name,email, COUNT(*) AS Occurence
    FROM NewTable
    GROUP BY name,email
    HAVING COUNT(*)>1

여기에 이미지 설명 입력

구조:

  • GROUP BY 절은 이름과 전자 메일 열의 값을 기준으로 행을 그룹으로 그룹화합니다.
  • 다음으로 COUNT() 함수는 각 그룹(이름, 이메일)의 발생 횟수를 반환합니다.
  • 그런 다음 HAVING 절은 중복된 그룹만 유지합니다. 중복된 그룹은 둘 이상의 오카렌스가 있는 그룹입니다.

2. CTE 사용:

중복된 각 행의 행 전체를 반환하려면 위의 쿼리 결과를NewTableCommon Table Expression(CTE; 공통 테이블 표현)을 사용한 테이블:

WITH cte AS (
    SELECT
        name, 
        email, 
        COUNT(*) occurrences
    FROM NewTable
    GROUP BY 
        name, 
        email
    HAVING COUNT(*) > 1
)
SELECT 
    t1.Id,
    t1.name, 
    t1.email
FROM  NewTable t1
    INNER JOIN cte ON 
        cte.name = t1.name AND 
        cte.email = t1.email
ORDER BY 
    t1.name, 
    t1.email;

여기에 이미지 설명 입력

3. ROW_NUMBER() 함수를 사용한다.

WITH cte AS (
    SELECT 
        name, 
        email, 
        ROW_NUMBER() OVER (
            PARTITION BY name,email
            ORDER BY name,email) rownum
    FROM 
        NewTable t1
) 
SELECT 
  * 
FROM 
    cte 
WHERE 
    rownum > 1;

여기에 이미지 설명 입력

구조:

  • ROW_NUMBER()의 행을 배포합니다.NewTable값을 기준으로 분할된 테이블name그리고.email컬럼을 클릭합니다.중복된 행의 경우,name그리고.email열이지만 행 번호가 다릅니다.
  • Outer 쿼리는 각 그룹의 첫 번째 행을 삭제합니다.

이제 중복을 찾는 방법에 대한 건전한 아이디어를 얻을 수 있고 모든 가능한 시나리오에서 중복을 찾는 논리를 적용할 수 있습니다.감사해요.

이게 너에게 도움이 될 것 같아

SELECT name, email, COUNT(* ) 
FROM users
GROUP BY name, email
HAVING COUNT(*)>1

테이블에 중복된 행이 있는지 확인하려면 아래 쿼리를 사용했습니다.

create table my_table(id int, name varchar(100), email varchar(100));

insert into my_table values (1, 'shekh', 'shekh@rms.com');
insert into my_table values (1, 'shekh', 'shekh@rms.com');
insert into my_table values (2, 'Aman', 'aman@rms.com');
insert into my_table values (3, 'Tom', 'tom@rms.com');
insert into my_table values (4, 'Raj', 'raj@rms.com');


Select COUNT(1) As Total_Rows from my_table 
Select Count(1) As Distinct_Rows from ( Select Distinct * from my_table) abc 

SELECT id, COUNT(id) FROM table1 GROUP BY id HAVING COUNT(id)>1;

이것은 특정 컬럼에서 반복된 값을 검색하기 위해 적절하게 작동한다고 생각합니다.

select id,name,COUNT(*) from user group by Id,Name having COUNT(*)>1
 select emp.ename, emp.empno, dept.loc 
          from emp
 inner join dept 
          on dept.deptno=emp.deptno
 inner join
    (select ename, count(*) from
    emp
    group by ename, deptno
    having count(*) > 1)
 t on emp.ename=t.ename order by emp.ename
/

이게 내가 생각해낸 가장 쉬운 것이다.Common Table Expression(CTE; 공통 테이블 표현)과 파티션 창을 사용합니다(이러한 기능은 SQL 2008 이후인 것 같습니다).

이 예에서는 중복된 이름과 dob을 가진 모든 학생을 찾습니다.중복 여부를 확인하는 필드는 OVER 절에 있습니다.투영에 원하는 다른 필드를 포함할 수 있습니다.

with cte (StudentId, Fname, LName, DOB, RowCnt)
as (
SELECT StudentId, FirstName, LastName, DateOfBirth as DOB, SUM(1) OVER (Partition By FirstName, LastName, DateOfBirth) as RowCnt
FROM tblStudent
)
SELECT * from CTE where RowCnt > 1
ORDER BY DOB, LName

중복된 값은 어떻게 셀 수 있습니까?2번 이상 반복하거나 2번 이상 반복하거나 그룹 와이즈가 아니라 그냥 세어보세요.

처럼 단순한

select COUNT(distinct col_01) from Table_01

CTE를 사용하면 이와 같은 중복값을 찾을 수 있습니다.

with MyCTE
as
(
select Name,EmailId,ROW_NUMBER() over(PARTITION BY EmailId order by id) as Duplicate from [Employees]

)
select * from MyCTE where Duplicate>1

이것 또한 효과가 있을 것입니다.어쩌면 한번 시도해 보세요.

  Select * from Users a
            where EXISTS (Select * from Users b 
                where (     a.name = b.name 
                        OR  a.email = b.email)
                     and a.ID != b.id)

특히 메일의 새 도메인과 같은 접두사 또는 일반적인 변경 사항이 있는 중복 항목을 검색하는 경우 유용합니다.이러한 컬럼에서 replace()를 사용할 수 있습니다.

SELECT * FROM users u where rowid = (select max(rowid) from users u1 where
u.email=u1.email);
SELECT name, email,COUNT(email) 
FROM users 
WHERE email IN (
    SELECT email 
    FROM users 
    GROUP BY email 
    HAVING COUNT(email) > 1)

여기서 가장 중요한 것은 가장 빠른 기능을 갖는 것이다.또한 중복 인덱스를 식별해야 한다.자체 결합은 좋은 옵션이지만, 더 빠른 기능을 가지려면 먼저 중복된 행을 찾은 다음 중복된 행의 ID를 찾기 위해 원래 테이블과 결합하는 것이 좋습니다.마지막으로 id를 제외한 임의의 열에 따라 서로 중복된 행을 정렬합니다.

SELECT u.*
FROM users AS u
JOIN (SELECT username, email
      FROM users
      GROUP BY username, email
      HAVING COUNT(*)>1) AS w
ON u.username=w.username AND u.email=w.email
ORDER BY u.email;

중복된 데이터를 하나 또는 여러 기준으로 찾고 실제 행을 선택하려면 다음과 같이 하십시오.

with MYCTE as (
    SELECT DuplicateKey1
        ,DuplicateKey2 --optional
        ,count(*) X
    FROM MyTable
    group by DuplicateKey1, DuplicateKey2
    having count(*) > 1
) 
SELECT E.*
FROM MyTable E
JOIN MYCTE cte
ON E.DuplicateKey1=cte.DuplicateKey1
    AND E.DuplicateKey2=cte.DuplicateKey2
ORDER BY E.DuplicateKey1, E.DuplicateKey2, CreatedAt

http://developer.azurewebsites.net/2014/09/better-sql-group-by-find-duplicate-data/

이름이 중복된 레코드를 삭제하려면 다음과 같이 하십시오.

;WITH CTE AS    
(

    SELECT ROW_NUMBER() OVER (PARTITION BY name ORDER BY name) AS T FROM     @YourTable    
)

DELETE FROM CTE WHERE T > 1

테이블의 중복된 레코드에서 체크하려면

select * from users s 
where rowid < any 
(select rowid from users k where s.name = k.name and s.email = k.email);

또는

select * from users s 
where rowid not in 
(select max(rowid) from users k where s.name = k.name and s.email = k.email);

테이블에서 중복 레코드를 삭제하려면

delete from users s 
where rowid < any 
(select rowid from users k where s.name = k.name and s.email = k.email);

또는

delete from users s 
where rowid not in 
(select max(rowid) from users k where s.name = k.name and s.email = k.email);

분석 기능을 사용하여 이를 시도할 수 있는 또 다른 쉬운 방법은 다음과 같습니다.

SELECT * from 

(SELECT name, email,

COUNT(name) OVER (PARTITION BY name, email) cnt 

FROM users)

WHERE cnt >1;

SELECT column_name,COUNT(*) FROM TABLE_NAME GROUP BY column1, HAVING COUNT(*) > 1;

이거 드셔보세요.

SELECT NAME, EMAIL, COUNT(*)
FROM USERS
GROUP BY 1,2
HAVING COUNT(*) > 1

언급URL : https://stackoverflow.com/questions/2594829/finding-duplicate-values-in-a-sql-table