🧖

【Rails】ゆるくおさえるActive RecordクエリIF

2022/07/24に公開約4,200字

ととのっていきましょう。最近業務でRailsを触りはじめました。
Active RecordのクエリIFがいろいろとあるようなので、Railsガイドからピックアップしてまとめていきます。
正確な情報はRailsガイドをあたるのがいいですが、クエリIFをかいつまむのに参考になればと。

サンプルコードで使うデータのER図

後に紹介するActive RecordクエリIFのサンプルコードは、↓のデータモデルを使ったものです。

*画像はRailsガイドより

Active RecordクエリIF一覧

IF 概要 サンプルコード SQL
find 指定した主キー(id)のレコードを取得する。 Customer.find(10) SELECT * FROM customers WHERE customers.id = 10 LIMIT 1
first 主キー順の最初のレコードを取得する。 Customer.first SELECT * FROM customers ORDER BY customers.id ASC LIMIT 1
last 主キー順の最後のレコードを取得する。 Customer.last SELECT * FROM customers ORDER BY customers.id DESC LIMIT 1
find_by 与えられた条件にマッチするレコードのうち最初のレコードを取得する。 Customer.find_by(first_name: 'Lifo') SELECT * FROM customers WHERE customers.first_name = 'Lifo' LIMIT 1
where(単一条件) 指定した1つの条件にマッチするレコードを取得する。 Book.where("title = ?", params[:title]) SELECT * FROM books WHERE books.title = ?
where(複数条件) 指定した複数の条件にマッチするレコードを取得する。 Book.where("title = ? AND out_of_print = ?", params[:title], false)) SELECT * FROM books WHERE books.title = ? AND books.out_of_print = 0
where(範囲条件) 指定した範囲にマッチするレコードを取得する。 Book.where(created_at: (Time.now.midnight - 1.day)..Time.now.midnight) SELECT * FROM books WHERE books.created_at BETWEEN '2008-12-21 00:00:00' AND '2008-12-22 00:00:00'
where(NOT条件) 指定した否定条件にマッチするレコードを取得する。 Customer.where.not(orders_count: [1,3,5]) SELECT * FROM customers WHERE customers.orders_count NOT IN (1,3,5)
order(昇順) 昇順で並び替えられたレコードを取得する。 Book.order(created_at: :asc) SELECT * FROM books ORDER BY created_at ASC
order(降順) 降順で並び替えられたレコードを取得する。 Book.order(title: :desc, created_at: :desc) SELECT * FROM books ORDER BY title DESC, created_at DESC
select 指定したカラムを取得する。 Book.select(:isbn, :out_of_print) SELECT isbn, out_of_print FROM books
distinct 指定したカラムを値の重複なく取得する。 Customer.select(:last_name).distinct SELECT DISTINCT last_name FROM customers
limit 指定した数のレコードを取得する。 Customer.limit(5) SELECT * FROM customers LIMIT 5
offset 指定した数のレコードをスキップしてレコードを取得する。 Customer.limit(5).offset(30) SELECT * FROM customers LIMIT 5 OFFSET 30
group グループ化した項目ごとにレコードを取得する。 Order.group(:status).count SELECT COUNT(*), status FROM orders GROUP BY status
having グループ化された項目について指定した条件にマッチするレコードを取得する。 Order.select("created_at, sum(total)")
.group("created_at")
.having("sum(total) > ?", 200)
SELECT created_at, SUM(total) FROM orders GROUP BY created_at HAVING SUM(total) > 200
joins(内部結合) テーブルを内部結合する。 Book.joins(:reviews) SELECT books.* FROM books INNER JOIN reviews ON reviews.book_id = books.id
left_outer_joins(左外部結合) テーブルを左外部結合する。 Book.left_outer_joins(:reviews) SELECT books.* FROM books LEFT OUTER JOIN reviews ON reviews.book_id = books.id
includes 指定した関連テーブルのレコードをキャッシュする。関連テーブルで絞り込みを行った場合はさらに左外部結合する。(N + 1クエリ問題解消) books = Book.includes(:author).limit(10)
books.each do |book|
   puts book.author.last_name
end
SELECT books* FROM books LIMIT 10
SELECT authors.* FROM authors WHERE authors.book_id IN (1,2,3,4,5,6,7,8,9,10)
preload 指定した関連テーブルのレコードをキャッシュする。(N + 1クエリ問題解消) books = Book.preload(:author).limit(10)
books.each do |book|
   puts book.author.last_name
end
SELECT books* FROM books LIMIT 10
SELECT authors.* FROM authors WHERE authors.book_id IN (1,2,3,4,5,6,7,8,9,10)
eager_load 指定した関連テーブルのレコードをキャッシュして左外部結合する。(N + 1クエリ問題解消) books = Book.eager_load(:author).limit(10)
books.each do |book|
   puts book.author.last_name
end
SELECT DISTINCT books.id FROM books LEFT OUTER JOIN authors ON authors.book_id = books.id LIMIT 10
SELECT books.id AS t0_r0, books.last_name AS t0_r1, ... FROM books LEFT OUTER JOIN authors ON authors.book_id = books.id WHERE books.id IN (1,2,3,4,5,6,7,8,9,10)
count 指定したカラムのレコード数を取得する。 Order.count(:subtotal) SELCT COUNT(subtotal) FROM orders
average 指定したカラムの平均を取得する。 Order.average(:subtotal) SELCT AVG(subtotal) FROM orders
minimum 指定したカラムの最小値を取得する。 Order.minimum(:subtotal) SELCT MIN(subtotal) FROM orders
maximum 指定したカラムの最大値を取得する。 Order.maximum(:subtotal) SELCT MAX(subtotal) FROM orders
sum 指定したカラムの合計を取得する。 Order.sum(:subtotal) SELCT SUM(subtotal) FROM orders

Discussion

ログインするとコメントできます