8

重複の可能性:
重複行を削除するにはどうすればよいですか?
MySQL クエリのみを使用して重複を削除しますか?

1,400 万エントリまでの大きなテーブルがあります。テーブル タイプは InnoDB ではなく MyISAM です。

残念ながら、このテーブルには、次のリクエストで見つけた重複するエントリがいくつかあります。

SELECT device_serial, temp, tstamp, COUNT(*) c FROM up_logs GROUP BY device_serial, temp, tstamp HAVING c > 1

今後これらの重複を避けるために、現在のインデックスを SQL request を使用して一意の制約に変換したいと思います。

ALTER TABLE  up_logs DROP INDEX UK_UP_LOGS_TSTAMP_DEVICE_SERIAL,
ALTER TABLE up_logs ADD INDEX UK_UP_LOGS_TSTAMP_DEVICE_SERIAL (  `tstamp` ,  `device_serial` )

しかし、その前に、重複をクリーンアップする必要があります!

私の質問は次のとおりです。重複したエントリのエントリを 1 つだけ保持するにはどうすればよいですか? 私のテーブルには 14M のエントリが含まれているため、可能であればループを避けたいと考えています。

どんなコメントでも大歓迎です!

4

3 に答える 3

4

一意として持つ必要がある列に新しい一意のキーを作成すると、テーブルの重複が自動的に消去されます。

ALTER IGNORE TABLE `table_name`
    ADD UNIQUE KEY `key_name`(`column_1`,`column_2`);

IGNORE部分では、最初のエラーが発生した後にスクリプトを終了できません。デフォルトの動作は、重複を削除することです。

于 2012-10-04T12:55:58.013 に答える
4

MySQL では update/delete ステートメントでサブクエリを使用できますが、更新するテーブルを参照する場合は許可されないため、最初に元のテーブルのコピーを作成します。それで:

DELETE FROM original_table 
WHERE id NOT IN( 
    SELECT id FROM copy_table 
    GROUP BY column1, column2, ...
);

しかし、14M のエントリを含むテーブルをコピーするには時間がかかると想像できます...コピーするときに保持する項目を選択すると、処理が速くなる可能性があります。

INSERT INTO copy_table 
    SELECT * FROM original_table 
    GROUP BY column1, column2, ...;

その後

DELETE FROM original_table 
WHERE id IN(
    SELECT id FROM copy_table
);

前回 MySQL と SQL を一般的に使用してからしばらく経ったので、パフォーマンスが向上したものがあると確信していますが、これは機能するはずです ;)

于 2012-10-04T14:03:24.837 に答える
1

これは、重複する行を削除する方法です...私の例を書いて、コードに適用する必要があります。Actors テーブルがIDあり、繰り返される行を削除したいfirst_name

mysql> select actor_id, first_name from actor_2;
+----------+-------------+
| actor_id | first_name  |
+----------+-------------+
|        1 | PENELOPE    |
|        2 | NICK        |
|        3 | ED          |
....
|      199 | JULIA       |
|      200 | THORA       |
+----------+-------------+

200 rows in set (0.00 sec)

-次の行に同じ first_name (繰り返し、そうでない場合は null) がある場合は、@a という変数を使用して ID を取得します。

mysql> select if(first_name=@a,actor_id,null) as first_names,@a:=first_name from actor_2 order by first_name;
+---------------+----------------+
|  first_names  | @a:=first_name |
+---------------+----------------+
|          NULL | ADAM           |
|            71 | ADAM           |
|          NULL | AL             |
|          NULL | ALAN           |
|          NULL | ALBERT         |
|           125 | ALBERT         |
|          NULL | ALEC           |
|          NULL | ANGELA         |
|           144 | ANGELA         |
...
|          NULL | WILL           |
|          NULL | WILLIAM        |
|          NULL | WOODY          |
|            28 | WOODY          |
|          NULL | ZERO           |
+---------------+----------------+
200 rows in set (0.00 sec)

-重複 ID のみを取得できるようになりました:

    mysql> select first_names from (select if(first_name=@a,actor_id,null) as first_names,@a:=first_name from actor_2 order by first_name) as t1;
    +-------------+
    | first_names |
    +-------------+
    |        NULL |
    |          71 |
    |        NULL |
     ...
    |          28 |
    |        NULL |
    +-------------+
    200 rows in set (0.00 sec)

-最後のステップ、削除しましょう!

mysql> delete from actor_2 where actor_id in (select first_names from (select if(first_name=@a,actor_id,null) as first_names,@a:=first_name from actor_2 order by first_name) as t1);
Query OK, 72 rows affected (0.01 sec)

-テーブルを確認してみましょう:

mysql> select count(*) from actor_2 group by first_name;
+----------+
| count(*) |
+----------+
|        1 |
|        1 |
|        1 |
...
|        1 |
+----------+
128 rows in set (0.00 sec)

動作します。質問があれば返信してください

于 2012-10-04T13:37:51.750 に答える