6

メール、名前、姓の 3 つの列を持つ MYSQL データベースに取り組んでいます。

私がする必要があるのは、次のような関数を使用できることがわかっている電子メールを重複排除することです (このクエリは、削除ではなくソートするためだけです)。

select distinct emails, name, surname from emails;

また

select emails, name, surname from emails group by emails having count(*) >= 2;

ただし、重複した電子メール アドレスが見つかった場合は、名前や姓の値が保持されているものであることを確認する必要もあります。

例えば:

|ID | メール | 名前 | 姓 |
|1 | bob@bob.com | ボブ | ポールソン |
|2 | bob@bob.com | | | | |

この場合、最初の結果を保持し、2 番目の結果を削除したいと思います。

「case」または「if」ステートメントの使用を検討していますが、それらの使用経験はありません。これらのステートメントで上記の関数を拡張しようとしましたが、役に立ちませんでした。

誰かが私を正しい方向に向けることができますか?

PS: 表の最初の列は、自動インクリメントされた ID 値です。

更新 1: これまでのところ、以下の @Bohemian の回答はうまく機能していますが、ある行には名前があるが姓がなく、次の行には名前がないが姓があるという重複したメールアドレスがある場合に失敗します。両方の記録を保持します。編集する必要があるのは、これら 2 つのレコードのいずれかが削除されるようにすることだけです。

更新 2: @Bohemian の回答は素晴らしいですが、さらにテストを行った結果、名前と姓のフィールドにデータがある重複した電子メール行がある場合にのみ機能するという根本的な欠陥があることがわかりました (上の表)。電子メールの重複があり、名前と姓の両方のフィールドが入力されている行がない場合、それらの行はすべて無視され、重複除去されません。

このクエリの最後のステップは、現在必要な条件を満たさない重複を削除する方法を見つけることです。1 つの行に名前だけが含まれ、もう 1 つの行に姓だけが含まれている場合、電子メールは保持することが重要であるため、どちらが削除されても問題ありません。

4

3 に答える 3

4

この DELETE クエリを使用できます。これは一般的であり、より多くのフィールドをサポートするように簡単に適応できます。

DELETE tablename.*
FROM
  tablename LEFT JOIN (
    SELECT MIN(id) min_id
    FROM
      tablename t INNER JOIN (
        SELECT
          emails, MAX((name IS NOT NULL) + (surname IS NOT NULL)) max_non_nulls
        FROM
          tablename
        GROUP BY
          emails) m
      ON t.emails=m.emails
         AND ((t.name IS NOT NULL) + (t.surname IS NOT NULL))=m.max_non_nulls
    GROUP BY
      t.emails) ids
  ON tablename.id=ids.min_id
WHERE
  ids.min_id IS NULL

ここでフィドルを参照してください。

このクエリは、すべての電子メールについて、null 以外のフィールドの最大数を返します。

SELECT
  emails,
  MAX((name IS NOT NULL) + (surname IS NOT NULL)) max_non_nulls
FROM
  tablename
GROUP BY
  emails

次に、このクエリを tablename と結合して、null 以外のフィールドの最大数を持つすべての電子メールの最小 ID を取得します。

SELECT MIN(id) min_id
FROM
  tablename t INNER JOIN (
    SELECT
      emails, MAX((name IS NOT NULL) + (surname IS NOT NULL)) max_non_nulls
    FROM
      tablename
    GROUP BY
      emails) m
  ON t.emails=m.emails
     AND ((t.name IS NOT NULL) + (t.surname IS NOT NULL))=m.max_non_nulls
GROUP BY
  t.emails

次に、このクエリで返されない ID を持つすべての行を削除しています。

于 2013-08-01T15:38:49.943 に答える
0

メール ID が重複しているレコードを削除する

delete 
    from duplicate_email where id in(
        select id from (
            select id, email from duplicate_email group by email having count(id) > 1) as id
    )

ただし、重複する電子メールが 1 つしかないレコードを削除できるという問題が 1 つあります。

于 2015-11-28T19:59:38.947 に答える