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

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

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

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

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



답변

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

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

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


답변

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  


답변

다음은 단일 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
)


답변

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로 그룹화 된 모든 행 집합이 있습니다. 그것들을 삭제하십시오.

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

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

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

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


답변

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

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

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

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


답변

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

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습니다. 두 필드를 기반으로하는 중복 레코드이며 해당 레코드를 무시합니다.

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


답변

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

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