どーも!
たかぽんです!
本日はDuplicateEmails、SQLの問題をやっていきます!
だいぶんやるのも慣れてきた気がしますが、時間ある土日等はmedium挑戦もありかも......と思い始めてます!
もうしばらくeasy頑張るつもりですが...!
ではやっていいます!
Duplicate Emails
今回の問題は以下です。
問題としては最近やっているものと似ていますが...
データベースのテーブルに全く同じ値が入ったカラムが存在していて、その中から重複したものを調べる...といった内容になっています。
例えば...
引用になりますが、以下のようなテーブルがあった場合...
+----+---------+
| Id | Email |
+----+---------+
| 1 | a@b.com |
| 2 | c@d.com |
| 3 | a@b.com |
+----+---------+
Id=1, Id=3のカラムのEmailの値が重複しています。
そのため、今回はその値を返せばOKです。
+---------+
| Email |
+---------+
| a@b.com |
+---------+
案外簡単・・・?に見えてちょっと難しいですね...!
それでは次にアルゴリズム検討していきます...!
アルゴリズム
さて、筆者が考えたこととして、まず重複しているカラムを全て洗い出し、そのカラムをDISTINCTを使用して出力は重複ごとに一つにする...
といった具合で検討しました。
例えば以下の場合...
+----+---------+
| Id | Email |
+----+---------+
| 1 | a@b.com |
| 2 | c@d.com |
| 3 | a@b.com |
+----+---------+
上記から、Idが異なり、Emailが等しい部分のみ取り出します。
+---------+
| Email |
+---------+
| a@b.com |
| a@b.com |
+---------+
これに対して、DISTINCT句で重複を除くと...
+---------+
| Email |
+---------+
| a@b.com |
+---------+
こうなる想定です。
今回も自分自身の他の値との比較を使いたいため...
INNER JOINで自己結合を行います。
select p1.Email from Person p1 INNER JOIN Person p2
selectする内容はEmailが必要ですが、今回に関してはp1, p2どちらから取得しても大丈夫です。(Emailが等しいカラムを取得するはずなので。)
これで、比較に必要な情報は揃いました。
では、次に、条件です。
条件としては...Personテーブルで全く同じ値のp1, p2テーブルがあった場合、idが異なり、Emailが等しいカラムだけSELECTするようにします。
where p1.id != p2.id
and p1.Email = p2.Email
これによって、出力に関しては以下のようになるはずです。(ちょっとみづらいですが、Emailカラムにa@b.comという値が二つの形です。)
{"headers": ["Email"], "values": [["a@b.com"], ["a@b.com"]]}
// 上記は以下と同義
+---------+
| Email |
+---------+
| a@b.com |
| a@b.com |
+---------+
ただ、この時点では、p1.IDが1, 3, でそれぞれEmailが等しい場合があるため、Emailの出力は二つ出てしまいます。
さらに同じような値のカラム(三重に重複)がある場合はこれが3カラムになります。
そのため、最後にこの値をSELECTする際にDISTINCT句で重複を消してあげれば...
+---------+
| Email |
+---------+
| a@b.com |
+---------+
完成です!
最後に、完成形のコード貼っておきます。
提出したコード
最後に提出したコード貼っておきます。
以下、結果です。
Runtime: 291 ms, faster than 77.90% of MySQL online submissions for Duplicate Emails.
Memory Usage: 0B, less than 100.00% of MySQL online submissions for Duplicate Emails.
以下、コードです。
# Write your MySQL query statement below
select DISTINCT p1.Email from Person p1 INNER JOIN Person p2
where p1.id != p2.id
and p1.Email = p2.Email