データのテーブルがあり、ユーザーの送信から多くの重複エントリがあります。
subscriberEmail
元の送信のみを残して、 field に基づいてすべての重複行を削除したいと考えています。
つまり、重複するメールをすべて検索し、それらの行を削除して元のメールだけを残したいということです。
テーブルを交換せずにこれを行うにはどうすればよいですか?
私のテーブルには、各行の一意の ID が含まれています。
データのテーブルがあり、ユーザーの送信から多くの重複エントリがあります。
subscriberEmail
元の送信のみを残して、 field に基づいてすべての重複行を削除したいと考えています。
つまり、重複するメールをすべて検索し、それらの行を削除して元のメールだけを残したいということです。
テーブルを交換せずにこれを行うにはどうすればよいですか?
私のテーブルには、各行の一意の ID が含まれています。
どのレコードが「オリジナル」であるかの指標として id 列を使用しているため:
delete x
from myTable x
join myTable z on x.subscriberEmail = z.subscriberEmail
where x.id > z.id
これにより、メール アドレスごとに 1 つのレコードが残ります。
編集して追加:
上記のクエリを説明するには...
ここでのアイデアは、テーブルをそれ自体に対して結合することです。テーブルのコピーが 2 つあり、それぞれに異なる名前が付けられているとします。次に、それらを互いに比較して、最小の ID または各メール アドレスを見つけることができます。その後、後で作成された重複レコードが表示され、削除される可能性があります。(これを考えているとき、私はExcelを視覚化していました。)
テーブルに対してその操作を実行し、それをそれ自体と比較して、それぞれの側を識別できるようにするには、テーブル エイリアスを使用します。 x
テーブルのエイリアスです。from
so: のように節で割り当てられます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 インデックス付き列にすることを検討してください。
各行に一意の 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
);