...

【Rails】よく使うクエリメソッドをまとめてみたよ

Railsでよく使うクエリメソッドまとめ

どうもおはようポテト(@ohayoupoteto22)です。

クエリメソッドって色々あってよく分かんないや…

ということで今回は

「クエリメソッドって結局どんなのがあるの?」

「難しいのはいいからとりあえず基本的なクエリメソッドを知りたい」

という方に向けて「Railsのよく使う(と思われる)クエリメソッド」をまとめてみました。

初学者の備忘録ゆえ至らない点もあると思いますが参考になれば幸いです⸝⸝- ̫ -⸝⸝

ブログ主

早速いってみよう!

 

Railsのよく使うクエリメソッドまとめ

1列のみ取り出すクエリメソッド

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は指定したレコードをグループ化してくれます。

上の例でいうとその料理に使っている肉グループ化してくれてます。

ブログ主

joinsに関してはもう少し下で触れます

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

多くのメソッドは「!」を付けると破壊的になり、元のオブジェクト自体に変更を及ぼします。

order!,limit,offset!,select!,group!,having!,distinct!とかがあるね

ソロモン

 

関連付けされたモデルで使うクエリメソッド

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の数を減らすことができるものです。

ブログ主

「N+1問題」の対策になるやつだね

 

集計用のクエリメソッド

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は空の結果を取得してくれます。

あくまでnillではなく空の結果セットだから、eachとかで回そうとしてもエラーにならないんだね

ソロモン

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

コメントを残す

メールアドレスが公開されることはありません。

CAPTCHA