13

データのテーブルがあり、ユーザーの送信から多くの重複エントリがあります。

subscriberEmail元の送信のみを残して、 field に基づいてすべての重複行を削除したいと考えています。

つまり、重複するメールをすべて検索し、それらの行を削除して元のメールだけを残したいということです。

テーブルを交換せずにこれを行うにはどうすればよいですか?
私のテーブルには、各行の一意の ID が含まれています。

4

3 に答える 3

27

どのレコードが「オリジナル」であるかの指標として id 列を使用しているため:

delete x 
from myTable x
 join myTable z on x.subscriberEmail = z.subscriberEmail
where x.id > z.id

これにより、メール アドレスごとに 1 つのレコードが残ります。

編集して追加:

上記のクエリを説明するには...

ここでのアイデアは、テーブルをそれ自体に対して結合することです。テーブルのコピーが 2 つあり、それぞれに異なる名前が付けられているとします。次に、それらを互いに比較して、最小の ID または各メール アドレスを見つけることができます。その後、後で作成された重複レコードが表示され、削除される可能性があります。(これを考えているとき、私はExcelを視覚化していました。)

テーブルに対してその操作を実行し、それをそれ自体と比較して、それぞれの側を識別できるようにするには、テーブル エイリアスを使用します。 xテーブルのエイリアスです。fromso: のように節で割り当てられますfrom <table> <alias>x同じクエリの他の場所で使用して、そのテーブルをショートカットとして参照できるようになりました。

delete xアクションとターゲットでクエリを開始します。複数のテーブルからレコードを選択するクエリを実行し、 に表示されるレコードを削除しxます。

エイリアスは、テーブルの両方の「インスタンス」を参照するために使用されます。 from myTable x join myTable z on x.subscriberEmail = z.subscriberEmail電子メールが一致する場所でテーブルを自分自身にぶつけます。後続の where 句がないと、すべてのレコードが選択され、それ自体に対して結合される可能性があります。

このwhere句は、選択されるレコードを制限します。 where x.id > z.idエイリアス化された「インスタンス」に、電子メールに一致するがより高い値xを持つレコードのみを含めることができます。idテーブルに本当に必要なデータである一意の電子メール アドレス (ID が最小のもの) は含まxれず、削除されません。の唯一のレコードは、その電子メール アドレスの元のレコードよりもx高い重複レコード (電子メール アドレス) になりidます。

この場合、join 句と where 句を組み合わせることができます。

delete x 
  from myTable x 
  join myTable z
    on x.subscriberEmail = z.subscriberEmail
      and x.id > z.id

重複を防ぐために、subscriberEmail 列を UNIQUE インデックス付き列にすることを検討してください。

于 2010-09-08T20:28:53.917 に答える
0

各行に一意の ID がある場合は、次のようなことを試すことができます。2 番目の select ステートメントが必要な理由を聞かないでください。それ以外の場合、mysql は実行を許可しません。また、結果を一意にする列でグループ化します。

delete from my_table where id in (
  select id from (
    select id from my_table a group by subscriberEmail having count(*) > 1
  ) b
);
于 2010-09-08T20:58:51.557 に答える