Railsにおけるクエリ文
Railsにおいてコンソールでクエリ文を叩くと、ログにSQL文も表示される。これもしっかりみてどのような動きをしているのか観察しよう。
参考
orderメソッド
SQLのORDER BY節を作る。 指定したカラムの昇順(ASC)か降順(DESC)で並び替える。
@users = User.order(id: :desc) # idが10, 9, 8....である順にレコードが並び替えられる。 => [<User id: 10, name: trump, country: usa>, <User id: 9, name: abe, country: japan>... <User id: 1, name: putin, country: russia>]
joinsメソッド
SQLのJOIN節(INNER JOIN)をつくる。 引数のモデルと内部結合出来る。
@writers = User.joins(:articles) # articleが持つuserのidに対応する、全てのユーザーが表示される。 => [<User id: 10, name: honda, media: asahi>, <User id: 8, name: jimmy, media: foxnews>, <User id: 10, name: honda, media: asahi> <User id: 4, name: chen, media: cctv>.....]
Category.joins(:articles)
これは以下のSQL文に等しい。
SELECT categories.* FROM categories INNER JOIN articles ON articles.category_id = categories.id
groupメソッド
SQLにおけるGROUP BY句に該当。
Order.select("date(created_at) as ordered_date, sum(price) as total_price").group("date(created_at)")
これは以下のSQL文に等しい。
SELECT date(created_at) as ordered_date, sum(price) as total_price FROM orders GROUP BY date(created_at)
Havingメソッド
SQLにおけるGROUP BYフィールドで条件を指定する場合にHAVING句を使用するが、それに該当する。
Order.select("date(created_at) as ordered_date, sum(price) as total_price"). group("date(created_at)").having("sum(price) > ?", 100)
上の文は以下と等しい。
SELECT date(created_at) as ordered_date, sum(price) as total_price FROM orders GROUP BY date(created_at) HAVING sum(price) > 100
left_outer_joinsメソッド
関連レコードがあるかどうかにかかわらずレコードのセットを取得したいときに使う。外部結合。
Author.left_outer_joins(:posts).distinct.select('authors.*, COUNT(posts.*) AS posts_count').group('authors.id')
以下は上に同じ。
SELECT DISTINCT authors.*, COUNT(posts.*) AS posts_count FROM "authors" LEFT OUTER JOIN posts ON posts.author_id = authors.id GROUP BY authors.id
pluckメソッド
数としてカラム名のリストを与えると、指定したカラムの値の配列を、対応するデータ型で返す。Productモデルがあったとして、nameカラムの中身を確認したい場合はこのメソッドが有効である。
Product.pluck(:name) => ["Ruby on Rails Tote", "Ruby on Rails Bag", "Ruby on Rails Baseball Jersey", "Ruby on Rails Jr. Spaghetti", "Ruby on Rails Ringer T-Shirt", "Ruby Baseball Jersey", "Apache Baseball Jersey", "Ruby on Rails Mug", "Ruby on Rails Stein"] Product.pluck(:id,:name) => [[1, "Ruby on Rails Tote"], [2, "Ruby on Rails Bag"], [3, "Ruby on Rails Baseball Jersey"], [4, "Ruby on Rails Jr. Spaghetti"], [5, "Ruby on Rails Ringer T-Shirt"], [6, "Ruby Baseball Jersey"], [7, "Apache Baseball Jersey"], [8, "Ruby on Rails Mug"], [9, "Ruby on Rails Stein"]]
平均
テーブルに含まれる特定の数値の平均を得るには、そのテーブルを持つクラスに対してaverageメソッドを呼び出す。返される値は、そのカラムの平均値であり、通常3.14159265のような浮動小数点になる。
Client.average("orders_count")
最小
テーブルに含まれるカラムの最小値を得るには、そのテーブルを持つクラスに対してminimumメソッドを呼び出す。
Client.minimum("age")
最大
テーブルに含まれるカラムの最小値を得るには、そのテーブルを持つクラスに対してmaximumメソッドを呼び出す。
Client.maximum("age")
EXPLAINを実行する
explainの実行で、実行計画を見ることができる。
User.where(id: 1).joins(:articles).explain
メソッドチェーン
例文1
Person .select('people.id, people.name, comments.text') .joins(:comments) .where('comments.created_at > ?', 1.week.ago)
以下は上に同じ。
SELECT people.id, people.name, comments.text FROM people INNER JOIN comments ON comments.person_id = people.id WHERE comments.created_at > '2015-01-01'
例文2
Person .select('people.id, people.name, companies.name') .joins(:company) .find_by('people.name' => 'John') # 名を指定
以下は上に同じ。
SELECT people.id, people.name, companies.name FROM people INNER JOIN companies ON companies.person_id = people.id WHERE people.name = 'John' LIMIT 1
直にSQLを書く
独自のSQLを使用してレコードを検索したい場合、find_by_sqlメソッドを使用できる。このfind_by_sqlメソッドは、オブジェクトの配列を1つ返す。クエリがレコードを1つしか返さなかった場合にも配列が返される。
Client.find_by_sql("SELECT * FROM clients INNER JOIN orders ON clients.id = orders.client_id ORDER BY clients.created_at desc") # => [ # #<Client id: 1, first_name: "Lucas" >, # #<Client id: 2, first_name: "Jan" >, # ... # ]