いくつかのIDとタイトルを含むテーブルがあります。タイトル列を一意にしたいのですが、すでに60万件を超えるレコードがあり、そのうちのいくつかは重複しています(場合によっては数十回以上)。
1つを除いてすべての重複を削除して、後でUNIQUEキーをタイトル列に追加するにはどうすればよいですか?
このコマンドは、一意のキーを追加し、(一意のキーが原因で)エラーを生成するすべての行を削除します。これにより、重複が削除されます。
ALTER IGNORE TABLE table ADD UNIQUE KEY idx1(title);
編集:MySQLの一部のバージョンでは、このコマンド InnoDBテーブルでは機能しない可能性があります であることに注意してください。回避策については この投稿 を参照してください。 (この情報を提供してくれた「匿名ユーザー」に感謝します。)
元のテーブルの個別の行だけで新しいテーブルを作成します。他の方法があるかもしれませんが、私はこれが最もきれいだと思います。
CREATE TABLE tmp_table AS SELECT DISTINCT [....] FROM main_table
より具体的に :
より速い方法は、一時テーブルに個別の行を挿入することです。削除を使用すると、800万行のテーブルから重複を削除するのに数時間かかりました。インサートとディスティンクトを使用すると、わずか13分で完了しました。
CREATE TABLE tempTableName LIKE tableName;
CREATE INDEX ix_all_id ON tableName(cellId,attributeId,entityRowId,value);
INSERT INTO tempTableName(cellId,attributeId,entityRowId,value) SELECT DISTINCT cellId,attributeId,entityRowId,value FROM tableName;
DROP TABLE tableName;
INSERT tableName SELECT * FROM tempTableName;
DROP TABLE tempTableName;
以下のクエリを使用して、「id」フィールドの値が最も低い1つの行を除くすべての重複を削除できます。
DELETE t1 FROM table_name t1, table_name t2 WHERE t1.id > t2.id AND t1.name = t2.name
同様に、次のように「id」の値が最も高い行を保持できます。
DELETE t1 FROM table_name t1, table_name t2 WHERE t1.id < t2.id AND t1.name = t2.name
MySQLテーブルの重複を削除することは一般的な問題であり、通常、特定のニーズが伴います。誰かが興味を持っている場合は、ここ( MySQLの重複行を削除 )一時テーブルを使用して、信頼性が高く高速な方法でMySQLの重複を削除する方法を説明します(さまざまな使用例の例を示します)。
この場合、次のようなものが機能します。
-- create a new temporary table
CREATE TABLE tmp_table1 LIKE table1;
-- add a unique constraint
ALTER TABLE tmp_table1 ADD UNIQUE(id, 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;
MySql ALTER IGNORE TABLE
廃止予定 、インデックスを追加する前に、重複する日付を実際に削除する必要があります。
最初に、すべての重複を見つけるクエリを記述します。ここでは、email
が重複を含むフィールドであると想定しています。
SELECT
s1.email
s1.id,
s1.created
s2.id,
s2.created
FROM
student AS s1
INNER JOIN
student AS s2
WHERE
/* Emails are the same */
s1.email = s2.email AND
/* DON'T select both accounts,
only select the one created later.
The serial id could also be used here */
s2.created > s1.created
;
次に、一意の重複IDのみを選択します。
SELECT
DISTINCT s2.id
FROM
student AS s1
INNER JOIN
student AS s2
WHERE
s1.email = s2.email AND
s2.created > s1.created
;
削除する重複IDのみが含まれていることを確認したら、削除を実行します。追加する必要があります(SELECT * FROM tblname)
MySqlが文句を言わないように。
DELETE FROM
student
WHERE
id
IN (
SELECT
DISTINCT s2.id
FROM
(SELECT * FROM student) AS s1
INNER JOIN
(SELECT * FROM student) AS s2
WHERE
s1.email = s2.email AND
s2.created > s1.created
);
次に、一意のインデックスを作成します。
ALTER TABLE
student
ADD UNIQUE INDEX
idx_student_unique_email(email)
;
これは、SQL2000でそれを行う方法を示しています。私はMySQL構文に完全に精通していませんが、同等のものがあると確信しています
create table #titles (iid int identity (1, 1), title varchar(200))
-- Repeat this step many times to create duplicates
insert into #titles(title) values ('bob')
insert into #titles(title) values ('bob1')
insert into #titles(title) values ('bob2')
insert into #titles(title) values ('bob3')
insert into #titles(title) values ('bob4')
DELETE T FROM
#titles T left join
(
select title, min(iid) as minid from #titles group by title
) D on T.title = D.title and T.iid = D.minid
WHERE D.minid is null
Select * FROM #titles
delete from student where id in (
SELECT distinct(s1.`student_id`) from student as s1 inner join student as s2
where s1.`sex` = s2.`sex` and
s1.`student_id` > s2.`student_id` and
s1.`sex` = 'M'
ORDER BY `s1`.`student_id` ASC
)
Nitinが投稿したソリューションは、最もエレガントで論理的なソリューションのようです。
ただし、1つの問題があります。
エラー1093(HY000):FROM句で更新するターゲットテーブル '学生'を指定できません
ただし、これは、studentの代わりに(SELECT * FROM student)を使用して解決できます。
DELETE FROM student WHERE id IN (
SELECT distinct(s1.`student_id`) FROM (SELECT * FROM student) AS s1 INNER JOIN (SELECT * FROM student) AS s2
WHERE s1.`sex` = s2.`sex` AND
s1.`student_id` > s2.`student_id` AND
s1.`sex` = 'M'
ORDER BY `s1`.`student_id` ASC
)
元の解決策を考え出すために、あなたの+1をNitinに渡してください。