質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

2回答

3135閲覧

【Rails/SQL】条件付きで検索し、関連先テーブルのデータも一緒に取得したJSONをレスポンスとして返したい。【JOIN, SELECT, WHERE】

nyako

総合スコア45

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2021/08/22 09:33

編集2021/08/22 09:42

取得したい条件

usersテーブルのgenderカラムがmenのレコード全て + そのuser_idに紐づくcomment,evaluationを全て取得したいです。

ruby

1 2# usersテーブル (User.rb) 3has_many :comments 4 5id 6name 7email 8gender ( boolean, men or lady ) 9updated_at 10created_at 11 12 13# commentsテーブル (Comment.rb) 14belongs_to :users 15 16id 17comment 18evaluation 19updated_at 20created_at 21user_id(FK) 22 23

自分で考えたこと

まずテーブルを結合するためにjoinsで
User.joins(:comments)をする必要があると考えました。

またgenderを絞る必要があるので、where(gender: men)も加える必要があると考えました。

また色々調べているとselectでカラムを絞る必要がありそうです。

一旦、User.joins(:comments).select("*")としてgenderを絞らず関連先のテーブルも、全て取得できるのではないかと考えましたが上手く行きません。

他の方法だとして、結合ということをせず2回に分けて各テーブルを取得するのはテーブルを分けている理由がないなとも思ってました。

どのように取得するのが最適なのでしょうか。

宜しくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

ruby

1# 取得 2@users = User.where(gender: "men") 3# 出力 4@users.as_json(includes: {comments: { only: [:comment, :evaluation] }})

上記のコードでご希望の結果が得られると思いますが、
このコードでは as_json の中で user の数だけ comments を取得する SQL が発行される問題があります(N+1)。

log

1User Load (0.5ms) SELECT `users`.* FROM `users` 2Comment Load (0.6ms) SELECT `comments`.* FROM `comments` WHERE `comments`.`user_id` = 1 3Comment Load (0.6ms) SELECT `comments`.* FROM `comments` WHERE `comments`.`user_id` = 2 4Comment Load (0.6ms) SELECT `comments`.* FROM `comments` WHERE `comments`.`user_id` = 3 5...(user の数だけ繰り返される)

includes を指定することで comments をキャッシュする SQL が一回だけ発行され、 N+1 を防ぐことができます。

ruby

1@users = User.includes(:comments).where(gender: "men") 2@users.as_json(includes: {comments: { only: [:comment, :evaluation] }})

log

1User Load (0.5ms) SELECT `users`.* FROM `users` LIMIT 3 2Comment Load (0.6ms) SELECT `comments`.* FROM `comments` WHERE `comments`.`user_id` IN (1, 2, 3)

joins ではなく includes なのは、joins は検索用のメソッドであり、その結果はキャッシュされないからです。
詳しくは以下の記事をご確認ください。

ActiveRecordのjoinsとpreloadとincludesとeager_loadの違い

as_json
ActiveModel as_json のオプション一覧

投稿2021/09/06 05:06

neko_daisuki

総合スコア2090

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

やろうとしている事は正しそうに見えますね。Userモデルにhas_manyが記載されている前提で、こちらのように記述すると、ActiveRecordが生成した以下のようなSQLがRals serverを立ち上げたターミナルなどに表示されます。

ruby

1class User < ApplicationRecord 2 has_many :comments

ruby

1# genderに関わらずのUserとそのコメントを全て取得する 2User.joins(:comments).select("*")

sql

1SELECT * FROM `users` INNER JOIN `comments` ON `comments`.`user_id` = `users`.`id`

こちらのSQLをデータベースにログインして直接実行すると実際に取得したい値になっているかどうか確認できると思います。エラーが起きてないという事であれば、以下のように取得した結果をjsonに出力した結果はどうなるでしょうか

ruby

1p User.joins(:comments).select("*").as_json

投稿2021/09/06 03:13

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問