RailsでのIN

エンジニアの皆さん、こんにちは!
そうでない方も読んでいただきありがとうございます。

今日のテーマはIN

今日のお話はRailsのActive Recordを使ったときのIN句のお話です。

おさらい

そもそもSQLにおいてIN句はどんなときに使うのかというと、連続ではない複数の値を指定したいときに使います。
例えば、CountryテーブルのID1、3、4のデータが欲しいときにはIN句を使って指定してあげます。

SELECT * FROM Country where ID IN (1, 3, 4)

Railsでの書き方

これをRailsのActive Recordを使って書くとこのように書けます。

ids = [1, 3, 4]
Country.where('id IN (?)', ids)

予め配列に値を入れておく必要がありますね。

ちなみに、ID1,3,4以外のデータが欲しいときに使うNOT INはこうなります。

ids = [1, 3, 4]
Country.where('id NOT IN (?)', ids)

実は

わざわざIN句を書かなくてもIN句を発行してくれてしまうのが、Railsの良いところであり、悪いところだと思っています。なぜなら、意図せずにIN句を使えてしまうということになるからです。用法を良く知ってから使いたいものです。

こんな風にwhere文を書きます。

ids = [1, 3, 4]
Country.where(id: ids)

この時に発行されるクエリは以下のようになっています。

SELECT 'countries'.* FROM 'countries'
WHERE 'countries'.'id' IN (1, 3, 4)

ではIN句を指定したActive Recordから発行されるクエリはどうだったかというとこうでした。

SELECT 'countries'.* FROM 'countries'
WHERE (ID IN (1, 3, 4))

若干の表記の違いはありますが、どちらもIN句を発行しています。

実行速度はいかに

クエリは実行速度が大事ですよね。
実は両者でこんな違いがありました。

Load (0.3ms)
SELECT 'countries'.* FROM 'countries'
WHERE 'countries'.'id' IN (1, 3, 4)
Load (0.6ms)
SELECT 'countries'.* FROM 'countries'
WHERE (ID IN (1, 3, 4))

ということは、where文だけで完結させた方が良いかもしれないですね。。。。
ちょっと残念でした笑

最後に

INを指定しなくてもIN句が発行されるというのは、たまたま指定忘れて見つけたものでした。
が、意外と違いがあるし、むしろその方が効率が良いというのは新たな発見でした。