LoginSignup
4
4

More than 5 years have passed since last update.

Railsで AND,OR,副問い合わせを組み合わせたSQLを書く方法

Last updated at Posted at 2015-12-29

Rails 4.1でAND,OR,副問い合わせを組み合わせたSQLを書く方法

例えば以下のようなSQLを書きたいとき

SELECT date,name
FROM book
WHERE (date BETWEEN '2015-12-30' AND '2015-12-25'
AND ((columB = '1' OR columC = '1') OR columD = '1')
AND (date BETWEEN '2015-11-1' AND '2015-11-30' AND (columE = '1'))

Arelを使って書くことができます。

Arelインスタンス生成

上記SQLの3行目に該当します。

book_query=Table.arel_table[:date].in((5.days.ago)..(2015-12-30))

OR条件

上記SQLの4行目のカッコ内に該当します。
Arel::Nodes::Node#orを使います。

book_query_or=Book.arel_table[:columB].eq(1)
book_query_or=book_query_or.or(Book.arel_table[:columC].eq(1))
book_query_or=book_query_or.or(Book.arel_table[:columD].eq(1))

AND条件

Arel::Nodes::Node#andを使います。
上記SQLの3行目と4行目のカッコ内をANDでつなぐ処理です。

book_query = book_query.and(book_query_or)

副問い合わせ

上記SQLの5行目に該当します。
条件式の作り方は上述のAND条件の作成方法と同じです。
副問い合わせにするためにgroupingを使用するのがポイントです。
Arel::Nodes::Node#groupingを使います。

book_subquery = Table.arel_table[:date].in((30.days.ago)..(2015-11-30))
book_subquery = book_subquery.and(Book.arel_table[:columE].eq(1))
book_subquery = book_subquery.grouping(book_subquery)

SQL実行

最後に今まで構築した条件式をクエリに投入して実行します。
(2015-01-01修正 副問い合わせ用のwhere句を追加)

Book.select("date,name").where(book_query).where('columE in (?)',Book.select("columE").where(book_subquery ))

このようにすれば、上記のSQLが発行できます。
それぞれのメソッドを組み合わせれば、なかなか複雑なクエリもかけそうです。
ただ、Rails4.2のArelでのOR条件作成では以下のような問題もあるようです。
http://qiita.com/joker1007/items/5c851526e73b3bc0273a

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4