くるみ
- Railsのクエリメソッドってどんなのがあったけ?
- 難しいのはいいからとりあえず基本的なクエリメソッドを知りたい
という方に向けて「Railsのよく使う(と思われる)クエリメソッド」をまとめてみました。
初学者の備忘録ゆえ至らない点もあると思いますが参考になれば幸いです⸝⸝- ̫ -⸝⸝
Railsのよく使うクエリメソッドまとめ
基本的なクエリメソッド
find
Food.find(1)
#=> SELECT "foods".* FROM "foods" WHERE "foods"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
findは主キーを指定してレコードを検索します。
find_by
Food.find_by(name:"唐揚げ")
#=> SELECT "foods".* FROM "foods" WHERE "foods"."name" = ? LIMIT ? [["name", "唐揚げ"], ["LIMIT", 1]]
fond_byは特定の列で検索をかけて最初にヒットした1件を取得します。
where
Food.where(rank:2)
#=> SELECT "foods".* FROM "foods" WHERE "foods"."rank" = ? [["rank", 2]]
whereは特定の列で検索をかけてヒットしたレコードを全て取得します。
not
Food.where.not(rank:2)
#=> SELECT "foods".* FROM "foods" WHERE "foods"."rank" != ? [["rank", 2]]
notは、whereと一緒に使うことでその条件に”当てはまらない”レコードを取得できます。
or
Food.where(name:"竜田揚げ").or(Food.where("rank>1"))
#=> SELECT "foods".* FROM "foods" WHERE ("foods"."name" = ? OR (rank>1)) [["name", "竜田揚げ"]]
orは条件式を結合してくれます。
上の例でいうと「nameが”唐揚げ”もしくはrankが1より大きい」の料理を取得できます。
order
Food.where("rank>1").order(:rank)
#=> SELECT "foods".* FROM "foods" WHERE (rank>1) ORDER BY "foods"."rank" ASC
orderはレコードを並び替えてくれます。
昇順か降順かの指定は省略可能で、指定しないとasc(昇順)になります。
Food.where("rank>1").order(rank: :desc)
=>SELECT "foods".* FROM "foods" WHERE (rank>1) ORDER BY "foods"."rank" DESC
指定するときはこんな感じ。
Food.where("rank>1").order(:rank).reverse_order
#=> SELECT "foods".* FROM "foods" WHERE (rank>1) ORDER BY "foods"."rank" DESC
reverse_orderで並び替えを逆にすることもできます。
reorder
Food.all.order(:rank).reorder(:id)
#=> SELECT "foods".* FROM "foods" ORDER BY "foods"."id" ASC
reorderは並び替えを上書きしてくれます。
first
Food.first
#=> SELECT "foods".* FROM "foods" ORDER BY "foods"."id" ASC LIMIT ? [["LIMIT", 1]]
firstは先頭(idが一番若い)のレコードを取得してくれます。
last
Food.last
#=> SELECT "foods".* FROM "foods" ORDER BY "foods"."id" DESC LIMIT ? [["LIMIT", 1]]
lastは末尾のレコードを取得してくれます。
select
Food.select(:rank)
#=> SELECT "foods"."rank" FROM "foods"
selectは指定した指定した列だけを取得してくれます。
limit & offset
Food.order(:rank).limit(810).offset(114514)
#=> SELECT "foods".* FROM "foods" ORDER BY "foods"."rank" ASC LIMIT ? OFFSET ? [["LIMIT",11], ["OFFSET", 114514]]
limitは取得するレコードの最大数を、offは取得する開始位置を指定してくれます。
上の例でいうと114515件目から最大810件を取得する、ってな具合です。
くるみ
distinct
Food.select(:rank).distinct
#=> SELECT DISTINCT "foods"."rank" FROM "foods"
distinctは重複しているレコードを取り除いてくれます。
上の例でいうと同じランクの料理は除外してくれてます。
Food.select(:name).distinct.distinct(false)
#=> SELECT "foods"."name" FROM "foods"
引数にfalseを指定して呼ぶことで前のdistinctを無効にすることもできます。
group
Food.joins(:meat).select("meats.name").group("meats.name")
#=> SELECT meats.name FROM "foods" INNER JOIN "meats" ON "meats"."id" = "foods"."meat_id" GROUP BY meats.name
groupは指定したレコードをグループ化してくれます。
上の例でいうとその料理に使っている肉グループ化してくれてます。
ブログ主
having
Food.joins(:meat).select("meats.name").group("meats.name").having("MAX(rank>4)")
#=> SELECT meats.name FROM "foods" INNER JOIN "meats" ON "meats"."id" = "foods"."meat_id" GROUP BY meats.name HAVING (MAX(rank>4))
havingを使うことでgroupでグループ化した後に条件を指定して絞り込むことができます。
破壊的なもの
@foods=Food.all
@foods.order!(:rank)
#=> SELECT "foods".* FROM "foods" ORDER BY "foods"."rank" ASC
@foods.where!("rank>3")
#=> SELECT "foods".* FROM "foods" WHERE (rank>3) ORDER BY "foods"."rank" ASC
多くのメソッドは「!」を付けると破壊的になり、元のオブジェクト自体に変更を及ぼします。
くるみ
関連付けされたモデルで使うもの
joins
Food.joins(:meat)
#=> SELECT "foods".* FROM "foods" INNER JOIN "meats" ON "meats"."id" = "foods"."meat_id"
joinsはテーブルを内部結合してくれます。
上の例でいうと1対多の関係にあるMeatテーブルとFoodテーブル、両方の結合条件にマッチするレコードのみを取得してくれます。
left_joins
Food.left_joins(:meat)
#=> SELECT "foods".* FROM "foods" LEFT OUTER JOIN "meats" ON "meats"."id" = "foods"."meat_id"
left_joinsはテーブルを左外部結合してくれます。
joinsとは違い、関連するレコードが無くても結合してくれます。
上の例でいうと、「使っているお肉がMeatテーブルに無い料理」があったFoodテーブルのレコードだとしても取得されます。
includes
Meat.includes(:foods)
#=> SELECT "meats".* FROM "meats"
#=> SELECT "foods".* FROM "foods" WHERE "foods"."meat_id" IN (?, ?, ?, ?) [["meat_id", 1],["meat_id", 2], ["meat_id", 3], ["meat_id", 4]]
includesは関連付けされたモデルをまとめて取得しておくことによって、発行されるSQLの数を減らすことができるものです。
ブログ主
集計用
count
Food.where("rank>2").count
#=> SELECT COUNT(*) FROM "foods" WHERE (rank>2)
countは行数をカウントしてくれます。
maximum / minimum
Food.maximum(:rank)
#=> SELECT MAX("foods"."rank") FROM "foods"
最大 / 最小。
sum
Food.sum(:rank)
#=> SELECT SUM("foods"."rank") FROM "foods"
合計。
average
Food.average(:rank)
#=> SELECT AVG("foods"."rank") FROM "foods"
平均。
その他
unscope
Food.where("rank>3").unscope(:where)
#=> SELECT "foods".* FROM "foods"
unscopeはクエリによる条件式を無効にしてくれます。
none
Food.none
noneは空の結果を取得してくれます。
くるみ
pluck
Food.where("rank>2").pluck(:name, :rank)
#=> [["竜田揚げ", 3], ["生姜焼き", 4], ["酢豚", 3], ["牛タン", 5], ["すき焼き", 4], ["ジンギスカン", 5]]
pluckメソッドは指定したカラムのレコードを配列として返してくれます。
exists?
Food.where(name:"牛カルビ").exists?
#=> SELECT 1 AS one FROM "foods" WHERE "foods"."name" = ? LIMIT ? [["name", "牛カルビ"], ["LIMIT", 1]]
#=> false
existsはレコードが存在するかどうか返してくれます。
まとめ
参考になれば幸いです!では⸝⸝- ̫ -⸝⸝
参考 【Rails】joinsメソッドのテーブル結合からネストまでの解説書Pikawaka