MySQL 테이블에서 중복을 삭제하는 방법은 무엇입니까?


158

테이블 DELETE에서 지정된 sid에 대한 행 을 복제 해야 MySQL합니다.

SQL 쿼리로 어떻게 할 수 있습니까?

DELETE (DUPLICATED TITLES) FROM table WHERE SID = "1"

이와 같은 것이지만 어떻게 해야할지 모르겠습니다.


한 번만 수행해야합니까, 아니면 항상 수행해야합니까?
Billy ONeal

중복 레코드가있는 레코드가 모두 동일한 데이터를 가지고 있거나 나머지 필드가 서로 다른가? 첫 번째 옵션이있는 경우 모든 레코드를 삭제하고 두 번째 옵션이있는 경우 유지하려는 레코드를 어떻게 결정합니까?
rael_kid

@Lex First 옵션. @ 빌리 나는 항상 그것을해야합니다.
Ali Demirci

1
가능한 중복 복제 MySQL에서 중복 행 제거
Basilevs

1
다양한 버전의 MySQL에서 여기에서 변경된 많은 것들이 있습니다. 여기에 솔루션의 경로를 뛰어 넘기 전에 MySQL 버전을주의 깊게 확인하십시오.
delatbabel

답변:


215

이것은 새로운 테이블을 만들지 않고 제자리에서 중복을 제거합니다.

ALTER IGNORE TABLE `table_name` ADD UNIQUE (title, SID)

참고 : 인덱스가 메모리에 맞는 경우에만 잘 작동합니다


26
주의 : 이렇게하면 가장 오래된 복제 레코드가 유지되고 새 레코드가 지워집니다. 최신 상태를 유지하려면이 작업을 수행 할 수 없습니다 ALTER IGNORE.
Haralan Dobrev

9
InnoDB에서 작동하지 않는 것 같습니다. 나는 ALTER TABLE foo ENGINE MyISAM그 문제를 해결하기 위해 달렸다 .
Martin

13
MySQL> 5.5에서는 실패 할 수 있습니다. "set session old_alter_table = 1;"을 사용하십시오. "set session old_alter_table = 0;" 성명서 전후
chillitom


2
@delatbabel 더 이상 사용되지 않는 이유는 연결된 페이지에 있습니다.
Barmar

133

employee다음 열 이있는 table이 있다고 가정합니다 .

employee (first_name, last_name, start_date)

중복 first_name열이 있는 행을 삭제하려면 다음을 수행하십시오 .

delete
from employee using employee,
    employee e1
where employee.id > e1.id
    and employee.first_name = e1.first_name  

1
나머지 레코드는 복제 그룹에서 최대 또는 최소 ID를 갖습니까?
Frozen Flame

이 조건을 충족하지 않는 유일한 삭제 될 수 있기 때문에 남아있는 기록은 최소 ID를해야합니다
파블로 게레로

1
employee하나의 인덱스 일치 에 대해 자체 에 대해 조인 >하고 인덱스에 대한 하나의 검사가 큰 테이블의 경우 느려질 것 같습니다. 더 나은을하지 않을까요 SELECT MAX(ID) FROM t GROUP BY uniqueJOIN정확히 일치에 IDMAX(ID)?
ebyrob 2016

1
좋은 답변입니다! 내 시간을 절약했습니다!
Nesar

56

다음은 단일 SID뿐만 아니라 모든 SID에 대해 중복을 제거합니다.

임시 테이블

CREATE TABLE table_temp AS
SELECT * FROM table GROUP BY title, SID;

DROP TABLE table;
RENAME TABLE table_temp TO table;

이후 temp_table새로 생성는 더 인덱스가 없습니다. 중복을 제거한 후 다시 만들어야합니다. 테이블에 어떤 인덱스가 있는지 확인할 수 있습니다.SHOW INDEXES IN table

임시 테이블이없는 경우 :

DELETE FROM `table` WHERE id IN (
  SELECT all_duplicates.id FROM (
    SELECT id FROM `table` WHERE (`title`, `SID`) IN (
      SELECT `title`, `SID` FROM `table` GROUP BY `title`, `SID` having count(*) > 1
    )
  ) AS all_duplicates 
  LEFT JOIN (
    SELECT id FROM `table` GROUP BY `title`, `SID` having count(*) > 1
  ) AS grouped_duplicates 
  ON all_duplicates.id = grouped_duplicates.id 
  WHERE grouped_duplicates.id IS NULL
)

4
그룹화는 그룹화 한 필드 값 조합마다 하나의 결과 행만 생성합니다. 따라서 중복이 제거됩니다.
Kamil Szot

4
나는 첫 번째 방법을 좋아합니다. 너무 우아합니다! : B
AgelessEssence

1
@fiacre 외래 키 검사를 일시적으로 비활성화 할 수 있습니다. stackoverflow.com/questions/15501673/… 다른 테이블이 참조하는 일부 행을 제거 할 위험이 있지만 쿼리를 변경하여 중복 제거 된 테이블에 대해 어떤 레코드가 선택되는지 제어 할 수 있습니다 SELECT * FROM table GROUP BY title, SID;그것은 당신이 무엇을 잘하는지에 달려 있습니다.
카밀 쇼트

1
@ahnbizcad 임시 테이블을 사용할 수 있지만 데이터를 임시 테이블에서 일반 테이블로 다시 복사해야합니다. 실제 테이블을 사용하는 경우 이전 테이블 이름을 복제하지 않고 이전 테이블을 삭제하고 새 테이블 이름을 바꿀 수 있습니다.
Kamil Szot 2016 년

1
"임시 테이블없이"방법은 최적의 솔루션에 가장 가까운 그러나 MySQL은 5.7.5에서 변경 ONLY_FULL_GROUP_BY 취급에주의입니다 : dev.mysql.com/doc/refman/5.7/en/group-by-handling.html 나는이있어 "SELECT id"를 "SELECT ANY_VALUE (id) AS id"로 교체하여 작동
delatbabel

53

MySQL에서 내부에서 중복 행 삭제 (시간 소인 열이 있다고 가정) 연습 :

테이블을 작성하고 일부 행을 삽입하십시오.

create table penguins(foo int, bar varchar(15), baz datetime);
insert into penguins values(1, 'skipper', now());
insert into penguins values(1, 'skipper', now());
insert into penguins values(3, 'kowalski', now());
insert into penguins values(3, 'kowalski', now());
insert into penguins values(3, 'kowalski', now());
insert into penguins values(4, 'rico', now());
select * from penguins;
    +------+----------+---------------------+
    | foo  | bar      | baz                 |
    +------+----------+---------------------+
    |    1 | skipper  | 2014-08-25 14:21:54 |
    |    1 | skipper  | 2014-08-25 14:21:59 |
    |    3 | kowalski | 2014-08-25 14:22:09 |
    |    3 | kowalski | 2014-08-25 14:22:13 |
    |    3 | kowalski | 2014-08-25 14:22:15 |
    |    4 | rico     | 2014-08-25 14:22:22 |
    +------+----------+---------------------+
6 rows in set (0.00 sec)

중복을 제자리에서 제거하십시오.

delete a
    from penguins a
    left join(
    select max(baz) maxtimestamp, foo, bar
    from penguins
    group by foo, bar) b
    on a.baz = maxtimestamp and
    a.foo = b.foo and
    a.bar = b.bar
    where b.maxtimestamp IS NULL;
Query OK, 3 rows affected (0.01 sec)
select * from penguins;
+------+----------+---------------------+
| foo  | bar      | baz                 |
+------+----------+---------------------+
|    1 | skipper  | 2014-08-25 14:21:59 |
|    3 | kowalski | 2014-08-25 14:22:15 |
|    4 | rico     | 2014-08-25 14:22:22 |
+------+----------+---------------------+
3 rows in set (0.00 sec)

완료, 중복 행이 제거되고 타임 스탬프로 마지막 행이 유지됩니다.

타임 스탬프 또는 고유 열이없는 사용자를 위해.

당신은 필요가 없습니다 timestamp에 의해 정렬 또는 고유 인덱스 컬럼을? 타락한 상태에 살고 있습니다. 중복 행을 삭제하려면 추가 단계를 수행해야합니다.

펭귄 테이블을 만들고 행을 추가하십시오

create table penguins(foo int, bar varchar(15)); 
insert into penguins values(1, 'skipper'); 
insert into penguins values(1, 'skipper'); 
insert into penguins values(3, 'kowalski'); 
insert into penguins values(3, 'kowalski'); 
insert into penguins values(3, 'kowalski'); 
insert into penguins values(4, 'rico'); 
select * from penguins; 
    # +------+----------+ 
    # | foo  | bar      | 
    # +------+----------+ 
    # |    1 | skipper  | 
    # |    1 | skipper  | 
    # |    3 | kowalski | 
    # |    3 | kowalski | 
    # |    3 | kowalski | 
    # |    4 | rico     | 
    # +------+----------+ 

첫 번째 테이블을 복제하여 복사하십시오.

drop table if exists penguins_copy; 
create table penguins_copy as ( SELECT foo, bar FROM penguins );  

#add an autoincrementing primary key: 
ALTER TABLE penguins_copy ADD moo int AUTO_INCREMENT PRIMARY KEY first; 

select * from penguins_copy; 
    # +-----+------+----------+ 
    # | moo | foo  | bar      | 
    # +-----+------+----------+ 
    # |   1 |    1 | skipper  | 
    # |   2 |    1 | skipper  | 
    # |   3 |    3 | kowalski | 
    # |   4 |    3 | kowalski | 
    # |   5 |    3 | kowalski | 
    # |   6 |    4 | rico     | 
    # +-----+------+----------+ 

최대 집계는 새로운 moo 지수에 따라 작동합니다.

delete a from penguins_copy a left join( 
    select max(moo) myindex, foo, bar 
    from penguins_copy 
    group by foo, bar) b 
    on a.moo = b.myindex and 
    a.foo = b.foo and 
    a.bar = b.bar 
    where b.myindex IS NULL; 

#drop the extra column on the copied table 
alter table penguins_copy drop moo; 
select * from penguins_copy; 

#drop the first table and put the copy table back: 
drop table penguins; 
create table penguins select * from penguins_copy; 

관찰 및 정리

drop table penguins_copy; 
select * from penguins;
+------+----------+ 
| foo  | bar      | 
+------+----------+ 
|    1 | skipper  | 
|    3 | kowalski | 
|    4 | rico     | 
+------+----------+ 
    Elapsed: 1458.359 milliseconds 

그 큰 SQL delete 문은 무엇입니까?

별명 'a'가있는 테이블 펭귄은 별명 'b'라는 테이블 펭귄의 서브 세트에 결합 된 채로 있습니다. 서브 세트 인 오른쪽 테이블 'b'는 열 foo 및 bar로 그룹화 된 최대 시간 소인 [또는 max moo]을 찾습니다. 이것은 왼쪽 테이블 'a'와 일치합니다. 왼쪽의 (foo, bar, baz)에는 테이블의 모든 행이 있습니다. 오른쪽 하위 집합 'b'에는 (maxtimestamp, foo, bar)가 있으며, 최대 값 인 왼쪽에만 일치합니다.

max가 아닌 모든 행은 maxtimestamp 값이 NULL입니다. 해당 NULL 행을 필터링하면 최신 타임 스탬프 baz가 아닌 foo 및 bar로 그룹화 된 모든 행 집합이 있습니다. 그것들을 삭제하십시오.

이를 실행하기 전에 테이블을 백업하십시오.

이 테이블에서이 문제가 다시 발생하지 않도록하십시오.

이 작업을 수행하면 "중복 행"화재가 발생합니다. 큰. 이제 테이블에 두 개의 열에 새로운 복합 고유 키를 정의하여 더 많은 중복이 처음에 추가되지 않도록합니다.

좋은 면역 체계와 마찬가지로 삽입시 잘못된 행을 테이블에 넣지 않아야합니다. 나중에 중복 프로그램을 추가하는 모든 프로그램에서 항의를 방송하고 문제를 해결하면이 문제는 다시 발생하지 않습니다.


6
마다가스카르 참조에 대한 순전히 평가하십시오!
Michael Wiggins 13:26에

1
Eric은 훌륭한 답변이며 훌륭한 제안이기 때문에 평가했습니다. Eric은 다른 답변보다 나은 결과를 얻었습니다.
요한

4
참고 : 테이블에 자동 증분 ID열 이 있으면 ON절이 ID열과 일치하기 만하면됩니다.
ebyrob 2016

1
나는 자세한 설명을 좋아하지만 ... 올바르게 이해하면이 답변은 타임 스탬프를 사용하여 레코드를 구별합니다. 그런 의미에서 레코드는 중복되지 않습니다. 레코드를 구별 할 타임 스탬프가없는 경우, 즉 모든 열이 두 개 이상의 레코드에 대해 동일하면 어떻게됩니까?
Rsc Rsc

1
@RscRsc 최대 집계를 적용 할 타임 스탬프 열 또는 고유 인덱스가없는 경우 테이블을 복제하고 고유 인덱스를 추가 한 후 delete 문을 적용한 다음 복사 된 테이블을 원래 테이블로 대체해야합니다. . 이 지침을 반영하여 답변을 변경했습니다.
Eric Leschinski

16

거대한 데이터베이스 에서이 문제를 직접 겪은 후에 다른 답변의 성능에 완전히 감명받지 못했습니다. 최신 중복 행만 유지하고 나머지는 삭제하고 싶습니다.

임시 테이블이없는 단일 쿼리 문에서 이것은 가장 효과적이었습니다.

DELETE e.*
FROM employee e
WHERE id IN
 (SELECT id
   FROM (SELECT MIN(id) as id
          FROM employee e2
          GROUP BY first_name, last_name
          HAVING COUNT(*) > 1) x);

유일한주의 사항은 쿼리를 여러 번 실행해야한다는 것입니다. 그러나 그럼에도 불구하고 다른 옵션보다 나에게 더 효과적이라는 것을 알았습니다.


1
실용적인 솔루션! 나를 위해 일했습니다-2m + 행 innodb 테이블의 경우 약 20 초입니다. 몇 번 사용하고 복제본이 많은 몇 명의 범죄자에게 귀가되면 수동으로 작업을 완료했습니다.
Troy Wray

1
한 번의 청소로 나를 위해 일했습니다.
Murwa

열에 대한 중복이 2 배 이상인 경우 여러 번 실행해야합니다.
PayteR

@PayteR은 답변에 "유일한 경고는 쿼리를 여러 번 실행해야한다는 것"이라고 언급 한 것입니다.
seaders

13

이것은 항상 나를 위해 작동하는 것 같습니다 :

CREATE TABLE NoDupeTable LIKE DupeTable; 
INSERT NoDupeTable SELECT * FROM DupeTable group by CommonField1,CommonFieldN;

각 속임수 및 나머지 비 속성 레코드에서 가장 낮은 ID를 유지합니다.

또한 제거 후 더 이상 속임수 문제가 발생하지 않도록 다음을 수행했습니다.

CREATE TABLE NoDupeTable LIKE DupeTable; 
Alter table NoDupeTable Add Unique `Unique` (CommonField1,CommonField2);
INSERT IGNORE NoDupeTable SELECT * FROM DupeTable;

즉, 첫 번째 테이블의 복제본을 만들고 중복을 원하지 않는 필드에 고유 인덱스를 추가 한 다음 처음 추가 할 때 Insert IGNORE와 같이 정상적으로 실패하지 않는 이점을 얻 Insert습니다. 두 필드를 기반으로하는 중복 레코드이며 해당 레코드를 무시합니다.

암호를 이동하면이 두 필드를 기반으로 중복 레코드를 작성하는 것이 불가능 해집니다.


1
어떤 레코드가 실제로 레코드를 대체하는지 확인하기 위해 ORDER BYin 이 필요하지 않습니까? SELECTNoDupeTable
ebyrob 2016

@ebyrob 별도의 지시가없는 한 다른 기준이 없으면 가장 낮은 ID를 선택합니다. 물론 ORDER by ID Asc상처를 줄 수 없으므로 그럼에도 불구하고 답변을 편집 할 것입니다.
user3649739

@ebyrob 죄송합니다. 이 선택에서는 Order by가 작동하지 않습니다. 선택이 끝날 때까지의 주문은 각 쌍에서 찾은 가장 낮은 ID로 찾은 사본 만 주문합니다. 또는 a를 수행 한 Select Max(ID)다음 Order by Max(ID)삽입 순서를 반대로하면됩니다. 가장 높은 ID를 얻으려면 위의 순서에 관계없이 더 낮은 ID에서 필드 값을 가져 오는 것처럼 더 복잡한 선택 조인이 필요합니다.
user3649739

사실, 내가 무엇을 생각하고 있는지 잘 모르겠습니다. 당신은 확실히 싶어 MAX(ID)MIN(ID)대신의 열 이름 *SELECT FROM DupeTable, 그렇지 않으면 당신은 단지 중 하나를 얻을 것이다,하지만 ID'무작위에요. 실제로, 많은 SQL 및 심지어 MySQL 엄격은 GROUP BY절에 지정되지 않은 각 열에서 집계 함수를 호출해야합니다 .
ebyrob

@ebyrob Max (ID) Min (ID) 테스트시 Max 또는 Mind 레코드의 ID를 반환하는 것 외에는 아무것도하지 마십시오. 각각의 경우에 동일한 레코드를 가져옵니다. 따라서 필드 ID,First,Last,Notes와 레코드 가있는 두 개의 레코드가 1,Bob,Smith,NULL있고 2,Bob,Smith,Arrears를 수행 SELECT *Max(ID), First,Last,Notes FROM DupeTable group by First,Last하면 다른 ID를 제외하고는 동일한 레코드 1을 반환합니다. Max (ID)가 반환 2,Bob,Smith,NULL되고 Min (ID)가 반환 1,Bob,Smith,NULL됩니다. 메모에 'Arrears'가있는 두 번째 레코드를 얻으려면 내가 믿는 조인이 필요합니다.
user3649739

7

다음은 모든 테이블에 적용됩니다.

CREATE TABLE `noDup` LIKE `Dup` ;
INSERT `noDup` SELECT DISTINCT * FROM `Dup` ;
DROP TABLE `Dup` ;
ALTER TABLE `noDup` RENAME `Dup` ;

6

간단한 답변은 다음과 같습니다.

delete a from target_table a left JOIN (select max(id_field) as id, field_being_repeated  
    from target_table GROUP BY field_being_repeated) b 
    on a.field_being_repeated = b.field_being_repeated
      and a.id_field = b.id_field
    where b.id_field is null;

작은 실수를 제외하고는 정답입니다and a.id_field = b.id
Vikrant Goel

LEFT JOIN으로 b만 비교해야 b.id= a.id_field가정하는 field_id독특한 자동 증가 ID입니다. 너무 a.field_being_repeated = b.field_being_repeated외래입니다. (또한 b.id_field이 쿼리에는 존재하지 않습니다 b.id.
ebyrob 11:10

6

이것은 오래된 레코드를 제거하는 데 도움이됩니다.

delete from table where id in 
(select min(e.id)
    from (select * from table) e 
    group by column1, column2
    having count(*) > 1
); 

최신 레코드를 제거하기 위해 min (e.id)를 max (e.id)로 바꿀 수 있습니다.


5
delete p from 
product p
inner join (
    select max(id) as id, url from product 
    group by url 
    having count(*) > 1
) unik on unik.url = p.url and unik.id != p.id;

1
내가 발견 것들 위보다 훨씬 더 성능이 좋은 솔루션
기독교 Butzke

5

의 Werner 솔루션 은 기본 키의 존재 여부에 관계없이 작동하고 테이블을 엉망으로 만들지 않고 미래를 보장하는 일반 SQL을 사용하며 매우 이해하기 쉽기 때문에 가장 편리합니다.

내 의견에서 언급했듯이 그 해결책은 올바르게 설명되지 않았습니다. 그래서 이것은 그것을 기반으로 한 내 것입니다.

1) 새로운 부울 열 추가

alter table mytable add tokeep boolean;

2) 복제 된 열과 새 열에 제약 조건을 추가하십시오.

alter table mytable add constraint preventdupe unique (mycol1, mycol2, tokeep);

3) 부울 열을 true로 설정하십시오. 이것은 새로운 제약 조건으로 인해 복제 된 행 중 하나에서만 성공합니다.

update ignore mytable set tokeep = true;

4) 유지로 표시되지 않은 행을 삭제하십시오.

delete from mytable where tokeep is null;

5) 추가 된 열을 삭제

alter table mytable drop tokeep;

추가 한 제한 조건을 유지하여 향후 새 복제본이 방지되도록하는 것이 좋습니다.


4

이 절차는 마지막 중복을 유지하면서 테이블의 모든 중복 (복수 포함)을 제거합니다. 이것은 각 그룹에서 마지막 레코드 검색 의 확장입니다

이것이 누군가에게 유용하기를 바랍니다.

DROP TABLE IF EXISTS UniqueIDs;
CREATE Temporary table UniqueIDs (id Int(11));

INSERT INTO UniqueIDs
    (SELECT T1.ID FROM Table T1 LEFT JOIN Table T2 ON
    (T1.Field1 = T2.Field1 AND T1.Field2 = T2.Field2 #Comparison Fields 
    AND T1.ID < T2.ID)
    WHERE T2.ID IS NULL);

DELETE FROM Table WHERE id NOT IN (SELECT ID FROM UniqueIDs);

4

UPDATE IGNORE를 사용하는 또 다른 쉬운 방법 :

U는 하나 이상의 열에 인덱스를 사용해야합니다 (타입 인덱스). 색인의 일부가 아닌 새 임시 참조 열을 작성하십시오. 이 열에서는 ignore 절로 고유 항목을 업데이트하여 고유 항목을 표시합니다. 단계별 :

고유 항목을 표시하기 위해 임시 참조 열을 추가하십시오.

ALTER TABLE `yourtable` ADD `unique` VARCHAR(3) NOT NULL AFTER `lastcolname`;

=> 테이블에 열을 추가합니다.

테이블을 업데이트하고 모든 것을 고유 한 것으로 표시하려고하지만 중복 키 문제로 인한 가능한 오류는 무시하십시오 (레코드는 생략 됨).

UPDATE IGNORE `yourtable` SET `unique` = 'Yes' WHERE 1;

=> 중복 레코드는 고유 = '예'로 표시되지 않습니다. 즉, 각 중복 레코드 세트 중 하나만 고유로 표시됩니다.

고유하지 않은 모든 항목을 삭제하십시오.

DELETE * FROM `yourtable` WHERE `unique` <> 'Yes';

=> 이렇게하면 모든 중복 레코드가 제거됩니다.

열을 버려라 ...

ALTER TABLE `yourtable` DROP `unique`;

테이블이 엉망이 아니며 일반 간단한 SQL을 사용하기 때문에 이것이 최선의 해결책이라고 생각합니다. 한 가지 확실한 unique점은 현재 복제 된 열과 함께 열을 고유 제약 조건에 추가해야한다는 것입니다. 그렇지 않으면 SET unique= '예'가 절대 실패 하지 않기 때문에 모든 것이 작동하지 않습니다 .
xtian April

또한 그것이 uniquemysql 키워드라는 것을 명심하십시오 . 따라서 백틱이 있어야합니다 (이미 올바르게 표시됨). 열에 다른 단어를 사용하는 것이 더 편리 할 수 ​​있습니다.
Torsten

2

MySQL 테이블에서 중복을 삭제하는 것은 일반적으로 특정 요구와 함께 발생하는 일반적인 문제입니다. 누구든지 관심이 있으시면 여기 ( MySQL에서 중복 행 제거 ) 임시 테이블을 사용하여 신뢰할 수 있고 빠른 방법으로 MySQL 복제본을 삭제하는 방법을 설명하고 빅 데이터 소스를 처리하는데도 유용합니다 (다른 사용 사례의 예 포함).

Ali 경우에는 다음과 같이 실행할 수 있습니다.

-- create a new temporary table
CREATE TABLE tmp_table1 LIKE table1;

-- add a unique constraint    
ALTER TABLE tmp_table1 ADD UNIQUE(sid, title);

-- scan over the table to insert entries
INSERT IGNORE INTO tmp_table1 SELECT * FROM table1 ORDER BY sid;

-- rename tables
RENAME TABLE table1 TO backup_table1, tmp_table1 TO table1;

0
delete from `table` where `table`.`SID` in 
    (
    select t.SID from table t join table t1 on t.title = t1.title  where t.SID > t1.SID
)

일부 구성 및 버전의 MySQL에서 SQL 오류 (1093)가 생성됩니다.
ebyrob 2016

0

@ eric의 대답을 좋아하지만 실제로 큰 테이블이 있으면 작동하지 않는 것 같습니다 ( The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okay실행하려고 할 때 나타납니다). 따라서 중복 쿼리 만 고려하도록 조인 쿼리를 제한하고 결과는 다음과 같습니다.

DELETE a FROM penguins a
    LEFT JOIN (SELECT COUNT(baz) AS num, MIN(baz) AS keepBaz, foo
        FROM penguins
        GROUP BY deviceId HAVING num > 1) b
        ON a.baz != b.keepBaz
        AND a.foo = b.foo
    WHERE b.foo IS NOT NULL

이 경우 WHERE 절을 사용하면 MySQL은 복제본이없는 행을 무시하고 이것이 복제본의 첫 번째 인스턴스 인 경우에도 무시하므로 후속 복제본 만 무시됩니다. 첫 번째 인스턴스 대신 마지막 인스턴스를 유지 MIN(baz)하도록 MAX(baz)로 변경하십시오 .


0

이것은 큰 테이블에서 작동합니다.

 CREATE Temporary table duplicates AS select max(id) as id, url from links group by url having count(*) > 1;

 DELETE l from links l inner join duplicates ld on ld.id = l.id WHERE ld.id IS NOT NULL;

가장 오래된 변경 사항 max(id)을 삭제하려면min(id)


0

여기서는 열 column_name을 기본 키로 만들고 그 동안 모든 오류를 무시합니다. 에 대한 중복 값이있는 행을 삭제합니다 column_name.

ALTER IGNORE TABLE `table_name` ADD PRIMARY KEY (`column_name`);

이전 답변에 대한 의견에서 언급했듯이 더 이상 5.7에서 작동하지 않습니다.
Barmar

0

기본적으로 테이블을 복사하고 비운 다음 고유 한 값만 다시 테이블에 넣어서 작동하지만 대량의 데이터에서 수행하기 전에 다시 확인하십시오.

테이블의 카본 사본을 만듭니다.

oldtablename과 같은 테이블 temp_table을 작성하십시오. temp_table 삽입 select * from oldtablename;

원래 테이블을 비 웁니다

삭제 * oldtablename에서;

복사 된 테이블의 모든 고유 값을 원래 테이블로 다시 복사합니다.

INSERT oldtablename SELECT * 이름, 성, dob로 temp_table 그룹에서

임시 테이블을 삭제합니다.

테이블 삭제 temp_table

명확하게 유지하려는 모든 필드를 기준으로 그룹화해야합니다.


0
DELETE T2
FROM   table_name T1
JOIN   same_table_name T2 ON (T1.title = T2.title AND T1.ID <> T2.ID)

요청이 작동하지 않습니다. 개선 할 수 있습니까?
Samir Guiderk

0

여기에 내가 보통 중복을 제거하는 방법이 있습니다

  1. 임시 열을 추가하고 원하는 이름을 지정하십시오 (활성으로 표시됩니다)
  2. 중복해서는 안되는 필드별로 그룹화하고 활성을 1로 설정하면 그룹화하면 해당 열에 대해 중복 값 중 하나만 선택합니다 (중복을 선택하지 않음)
  3. 활성 영점을 가진 것을 삭제하십시오
  4. 드롭 열 활성화
  5. 선택적으로 (귀하의 목적에 맞는 경우) 해당 열에 다시 중복되지 않도록 고유 인덱스를 추가하십시오.

-2

DISTINCT 절을 사용하여 "정리 된"목록을 선택할 수 있습니다 ( 이를 수행하는 방법에 대한 매우 쉬운 예는 다음 과 같습니다 ).


그 질문에 어떻게 대답합니까? 사용하여 DISTINCT당신은 당신이 처음에 있었다 수있는 중복에 대한 정보를 느슨한. 그것을 사용하여 중복을 삭제하는 방법을 보여줄 수 있습니까?
luk2302 2016 년

-3

당신이 그들을 세고 나서 하나만 남기고 삭제 쿼리에 제한을 추가하면 작동 할 수 있습니까?

예를 들어, 둘 이상인 경우 다음과 같이 쿼리를 작성하십시오.

DELETE FROM table WHERE SID = 1 LIMIT 1;

-5

테이블에서 중복 데이터를 제거 할 때 몇 가지 기본 단계가 있습니다.

  • 테이블을 백업하십시오!
  • 중복 행 찾기
  • 중복 행 제거

전체 자습서는 다음과 같습니다. https://blog.teamsql.io/deleting-duplicate-data-3541485b3473


고유 ID 만 다른 경우 작동합니까? 당신은 여기를 클릭하세요?
Andrew

기본적으로 여기에 설명 된 방법은 MySQL 버전> 5.7.5에서는 작동하지 않습니다. ONLY_FULL_GROUP_BY를 처리하기 때문입니다. 여기를 참조하십시오 : dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
delatbabel
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.