Rails の ActiveRecord を使っていると SQL ベタ書きしたり、Arel で書いたりする状況になることがある。そんな中で比較演算のケースは解決策があるのでメモっとく。
実行結果は Rails 4.2.1 で SQLite をデータベースとして利用しているときのもの。
範囲(BETWEEN 演算子)
where
に Range で指定することができるこの方法は有名。コードが綺麗になるし、Rails と SQL の間の違和感もない。
Person.where(age: 20..35)
生成される SQL はこうなる。
SELECT "people".* FROM "people" WHERE ("people"."age" BETWEEN 20 AND 35)
以上(>= 演算子)
前述の Range で以上(>= 演算子)を表現するとこうなる。(数学的には正しいけどさ……。って呆れて読むのをやめる前に生成される SQL も見てね。)
Person.where(age: 20..Float::INFINITY)
生成される SQL はこうなる。エラーにならずにきちんと >= 演算子を含む SQL が出力される。
SELECT "people".* FROM "people" WHERE ("people"."age" >= 20)
以下(<= 演算子)
同様に Range で以下(<= 演算子)を表現するとこうなる。
Person.where(age: -Float::INFINITY..20)
生成される SQL はこうなる。エラーにならずにきちんと <= 演算子を含む SQL が出力される。
SELECT "people".* FROM "people" WHERE ("people"."age" <= 20)
より小さい(< 演算子)
同様に Range でより小さい(< 演算子)を表現するとこうなる。
Person.where(age: -Float::INFINITY...20)
生成される SQL はこうなる。エラーにならずにきちんと < 演算子を含む SQL が出力される。
SELECT "people".* FROM "people" WHERE ("people"."age" < 20)
より大きい(> 演算子)
残念ながら Range でより大きい(> 演算子)は表現できない。
実用的かどうかは微妙なところだけど、数学的には真っ当な気がするから、見慣れたら便利かもしれない。まあトリビアとして知っておいてもいいんじゃないかな。いきなりプロジェクトで使うとチームのエンジニアからクレームが来るかもしれないので慎重にw
参考文献