테이블 DELETE
에서 지정된 sid에 대한 행 을 복제 해야 MySQL
합니다.
SQL 쿼리로 어떻게 할 수 있습니까?
DELETE (DUPLICATED TITLES) FROM table WHERE SID = "1"
이와 같은 것이지만 어떻게 해야할지 모르겠습니다.
테이블 DELETE
에서 지정된 sid에 대한 행 을 복제 해야 MySQL
합니다.
SQL 쿼리로 어떻게 할 수 있습니까?
DELETE (DUPLICATED TITLES) FROM table WHERE SID = "1"
이와 같은 것이지만 어떻게 해야할지 모르겠습니다.
답변:
이것은 새로운 테이블을 만들지 않고 제자리에서 중복을 제거합니다.
ALTER IGNORE TABLE `table_name` ADD UNIQUE (title, SID)
참고 : 인덱스가 메모리에 맞는 경우에만 잘 작동합니다
ALTER IGNORE
.
ALTER TABLE foo ENGINE MyISAM
그 문제를 해결하기 위해 달렸다 .
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
employee
하나의 인덱스 일치 에 대해 자체 에 대해 조인 >
하고 인덱스에 대한 하나의 검사가 큰 테이블의 경우 느려질 것 같습니다. 더 나은을하지 않을까요 SELECT MAX(ID) FROM t GROUP BY unique
후 JOIN
정확히 일치에 ID
에 MAX(ID)
?
다음은 단일 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
)
SELECT * FROM table GROUP BY title, SID;
그것은 당신이 무엇을 잘하는지에 달려 있습니다.
테이블을 작성하고 일부 행을 삽입하십시오.
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로 그룹화 된 모든 행 집합이 있습니다. 그것들을 삭제하십시오.
이를 실행하기 전에 테이블을 백업하십시오.
이 테이블에서이 문제가 다시 발생하지 않도록하십시오.
이 작업을 수행하면 "중복 행"화재가 발생합니다. 큰. 이제 테이블에 두 개의 열에 새로운 복합 고유 키를 정의하여 더 많은 중복이 처음에 추가되지 않도록합니다.
좋은 면역 체계와 마찬가지로 삽입시 잘못된 행을 테이블에 넣지 않아야합니다. 나중에 중복 프로그램을 추가하는 모든 프로그램에서 항의를 방송하고 문제를 해결하면이 문제는 다시 발생하지 않습니다.
ID
열 이 있으면 ON
절이 ID
열과 일치하기 만하면됩니다.
거대한 데이터베이스 에서이 문제를 직접 겪은 후에 다른 답변의 성능에 완전히 감명받지 못했습니다. 최신 중복 행만 유지하고 나머지는 삭제하고 싶습니다.
임시 테이블이없는 단일 쿼리 문에서 이것은 가장 효과적이었습니다.
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
습니다. 두 필드를 기반으로하는 중복 레코드이며 해당 레코드를 무시합니다.
암호를 이동하면이 두 필드를 기반으로 중복 레코드를 작성하는 것이 불가능 해집니다.
ORDER BY
in 이 필요하지 않습니까? SELECT
NoDupeTable
ORDER by ID Asc
상처를 줄 수 없으므로 그럼에도 불구하고 답변을 편집 할 것입니다.
Select Max(ID)
다음 Order by Max(ID)
삽입 순서를 반대로하면됩니다. 가장 높은 ID를 얻으려면 위의 순서에 관계없이 더 낮은 ID에서 필드 값을 가져 오는 것처럼 더 복잡한 선택 조인이 필요합니다.
MAX(ID)
나 MIN(ID)
대신의 열 이름 *
에 SELECT FROM DupeTable
, 그렇지 않으면 당신은 단지 중 하나를 얻을 것이다,하지만 ID
'무작위에요. 실제로, 많은 SQL 및 심지어 MySQL 엄격은 GROUP BY
절에 지정되지 않은 각 열에서 집계 함수를 호출해야합니다 .
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'가있는 두 번째 레코드를 얻으려면 내가 믿는 조인이 필요합니다.
간단한 답변은 다음과 같습니다.
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
LEFT JOIN
으로 b
만 비교해야 b.id
= a.id_field
가정하는 field_id
독특한 자동 증가 ID입니다. 너무 a.field_being_repeated = b.field_being_repeated
외래입니다. (또한 b.id_field
이 쿼리에는 존재하지 않습니다 b.id
.
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;
위 의 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;
추가 한 제한 조건을 유지하여 향후 새 복제본이 방지되도록하는 것이 좋습니다.
이 절차는 마지막 중복을 유지하면서 테이블의 모든 중복 (복수 포함)을 제거합니다. 이것은 각 그룹에서 마지막 레코드 검색 의 확장입니다
이것이 누군가에게 유용하기를 바랍니다.
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);
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`;
unique
점은 현재 복제 된 열과 함께 열을 고유 제약 조건에 추가해야한다는 것입니다. 그렇지 않으면 SET unique
= '예'가 절대 실패 하지 않기 때문에 모든 것이 작동하지 않습니다 .
unique
mysql 키워드라는 것을 명심하십시오 . 따라서 백틱이 있어야합니다 (이미 올바르게 표시됨). 열에 다른 단어를 사용하는 것이 더 편리 할 수 있습니다.
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;
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
)
@ 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)
로 변경하십시오 .
이것은 큰 테이블에서 작동합니다.
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)
여기서는 열 column_name
을 기본 키로 만들고 그 동안 모든 오류를 무시합니다. 에 대한 중복 값이있는 행을 삭제합니다 column_name
.
ALTER IGNORE TABLE `table_name` ADD PRIMARY KEY (`column_name`);
기본적으로 테이블을 복사하고 비운 다음 고유 한 값만 다시 테이블에 넣어서 작동하지만 대량의 데이터에서 수행하기 전에 다시 확인하십시오.
테이블의 카본 사본을 만듭니다.
oldtablename과 같은 테이블 temp_table을 작성하십시오. temp_table 삽입 select * from oldtablename;
원래 테이블을 비 웁니다
삭제 * oldtablename에서;
복사 된 테이블의 모든 고유 값을 원래 테이블로 다시 복사합니다.
INSERT oldtablename SELECT * 이름, 성, dob로 temp_table 그룹에서
임시 테이블을 삭제합니다.
테이블 삭제 temp_table
명확하게 유지하려는 모든 필드를 기준으로 그룹화해야합니다.
DELETE T2
FROM table_name T1
JOIN same_table_name T2 ON (T1.title = T2.title AND T1.ID <> T2.ID)
DISTINCT 절을 사용하여 "정리 된"목록을 선택할 수 있습니다 ( 이를 수행하는 방법에 대한 매우 쉬운 예는 다음 과 같습니다 ).
DISTINCT
당신은 당신이 처음에 있었다 수있는 중복에 대한 정보를 느슨한. 그것을 사용하여 중복을 삭제하는 방법을 보여줄 수 있습니까?
당신이 그들을 세고 나서 하나만 남기고 삭제 쿼리에 제한을 추가하면 작동 할 수 있습니까?
예를 들어, 둘 이상인 경우 다음과 같이 쿼리를 작성하십시오.
DELETE FROM table WHERE SID = 1 LIMIT 1;
테이블에서 중복 데이터를 제거 할 때 몇 가지 기본 단계가 있습니다.
전체 자습서는 다음과 같습니다. https://blog.teamsql.io/deleting-duplicate-data-3541485b3473