副問い合わせ(入れ子)でSQLを流したい
重複したデータを確認する例で確かめる。
副問い合わせの形を作る
usersテーブル
id | name | address |
---|---|---|
1 | sasaki | tokyo |
2 | itou | fukuoka |
3 | fujita | nagasaki |
4 | sasaki | osaka |
5 | itou | nagano |
例えば上のようなテーブルがあったとする。
nameが重複するレコードを取り出し、addressを確認したい。
sql1:nameが重複しているものを選択
SELECT name FROM users GROUP BY name HAVING count(name) > 1
結果
name |
---|
itou |
sasaki |
これだとそれぞれのaddressがわからないため、この結果を踏まえて次のようにSQLを実行する。
sql2:重複結果を踏まえて
SELECT * FROM users WHERE name IN ('itou', 'sasaki') ORDER BY name
結果
id | name | address |
---|---|---|
2 | itou | fukuoka |
5 | itou | nagano |
1 | sasaki | tokyo |
4 | sasaki | osaka |
上記のようになりこれでそれぞれのaddressも取得できる。
ということでsql1とsql2を合わせて副問い合わせの形にする。
sql3:副問い合わせ(sql1,sql2)
SELECT * FROM users WHERE name IN (
SELECT name FROM users GROUP BY name HAVING count(name) > 1
)
ORDER BY name
Railsで実装
結論
以下のように書くことができる
任意のコントローラ
duplicates = User.select(:name).group(:name).having("count(name) > 1")
@users = User.where(name: duplicates)
実行されるSQL
Railsにて実行されるSQL
SELECT "users".* FROM "users" WHERE "users"."name" IN (
SELECT "users"."name" FROM "users" GROUP BY "users"."name"
HAVING (count(name) > 1)
)
びっくりすることに発行されるSQLは1回になっている。
参考(かなり解りやすいです!)
ActiveRecord の IN 演算子でサブクエリを扱う(Oakbow様)