Ruby
Rails
rails4.1

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

More than 3 years have passed since last update.


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