INNER JOIN で中間テーブルを経由してデータ取得するとき、DISTINCT をつけても重複が削除できなくてハマった話です
データ
Users ユーザー情報
id | name |
---|---|
1 | Bob |
2 | Mary |
Tags タグ
id | name |
---|---|
1 | Engineer |
2 | Leader |
Tag_Users ユーザー情報とタグの中間テーブル
| user_id | tag_id |
|:-:|:-:|:-:|
| 1 | 1 |
| 2 | 1 |
| 1 | 2 |
BobはEngineer
MaryもEngineer
BobはLeader というデータとします
最初に書いたSQL
Engineer または Leader のユーザーを取得する必要があり、以下のようなSQL文を書きました
SELECT * FROM users INNER JOIN tag_users ON users.id = tag_users.user_id WHERE (tag_users.tags_id = 1 or tag_users.tags_id = 2);
表示された結果
users.id | users.name | tag_users.user_id | tag_users.tag_id |
---|---|---|---|
1 | Bob | 1 | 1 |
1 | Bob | 1 | 2 |
2 | Mary | 2 | 1 |
Bobが2人いますね
重複を削除しようと思って書いたSQL
SELECT DISTINCT * FROM users INNER JOIN tag_users ON users.id = tag_users.user_id WHERE (tag_users.tags_id = 1 or tag_users.tags_id = 2);
表示された結果
users.id | users.name | tag_users.user_id | tag_users.tag_id |
---|---|---|---|
1 | Bob | 1 | 1 |
1 | Bob | 1 | 2 |
2 | Mary | 2 | 1 |
Bobが重複しているのでDISTINCTを追加したけどBobは減らなかった
本当に必要だったSQL
SELECT DISTINCT users.* FROM users INNER JOIN tag_users ON users.id = tag_users.user_id WHERE (tag_users.tags_id = 1 or tag_users.tags_id = 2);
表示された結果
users.id | users.name |
---|---|
1 | Bob |
2 | Mary |
OK
結論
取得する範囲をきちんと指定する