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

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

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

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

Active Record

Active Recordは、一つのオブジェクトに対しドメインのロジックとストレージの抽象性を結合するデザインパターンです。

Q&A

解決済

3回答

728閲覧

ActiveRecordで書く場合の記述について

shori0128

総合スコア29

Ruby on Rails 5

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

Active Record

Active Recordは、一つのオブジェクトに対しドメインのロジックとストレージの抽象性を結合するデザインパターンです。

0グッド

0クリップ

投稿2020/01/28 09:57

いつもお世話になっています。

RailsのActiveRecordについて質問です。

以下のクエリをActiveRecordを使って記述する場合どのように記述すれば良いのでしょうか?

sql

1SELECT 2* 3FROM 4A_Table 5LEFT OUTER JOIN 6(SELECT * FROM B_TABLE WHERE id = 'xxxxx') B_Table 7ON A_Table.id = B_Table.id

やってほしいことだけを記載した丸投げの質問で申し訳ないのですが、かれこれ数時間ハマっています。
ActiveRecordを使うのは今回初めてで、SQLは書けるのですが、ActiveRecordの記述が理解できておらず四苦八苦しています。

みなさまお忙しいところ申し訳ないのですが、ご回答よろしくお願いします。

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

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

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

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

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

guest

回答3

0

Railsでは基本的に紐付けをa_tables.b_table_id = b_tables.idで行っており、それを元に結合します。今回の場合はそれに当てはまらないため、joinsの引数にSQLを直接書いていく必要があるかと思います。

提示されているSQLを発行するようなサンプルを書いてみました。
期待通りかどうかはわかりませんが、参考にしてください。

rb

1ATable.joins("LEFT OUTER JOIN (#{BTable.where(id: ***).to_sql}) b_tables ON a_tables.id = b_tables.id").select('*') 2# SELECT * FROM "a_tables" LEFT OUTER JOIN (SELECT "b_tables".* FROM "b_tables" WHERE "b_tables"."id" ***) b_tables ON a_tables.id = b_tables.id

投稿2020/01/29 04:27

編集2020/01/29 04:34
Mugheart

総合スコア2340

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

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

0

質問のSQLはかなり編集して キモ が変わっていませんか?
意味を理解しかねています。

「A_Table.id = B_Table.id という条件でjoinして」
はわかりますが、求めるのは A_Tableのcolumnだけ SELECT * FROM A_Table

ということは、
SELECT * FROM A_Table WHERE id = 'xxxxx'
と何が異なるのでしょう?

投稿2020/01/28 12:39

winterboum

総合スコア23284

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

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

shori0128

2020/01/28 14:10

>winterboumさん ご回答ありがとうございます。 いえ、B_tableの条件に一致するレコードとidが一致するA_table、B_tableの全てのカラムを取得するということです。 上記クエリはその動作になると認識していますが、ActiveRecordだとA_tableのレコードしか取得できないように見えるのでしょうか?
winterboum

2020/01/29 08:48

解決ですからよいのですが、それですとselectで列挙する必要がありますね
guest

0

ベストアンサー

サブクエリですが、以下のように二つに分けると分かりやすくて良いと思います。

B_id = B_table.find_by(id: "xxxxx").select(:id) A_table.where(id: B_id).all

MySQL

1SELECT 2* 3FROM 4A_Table 5LEFT OUTER JOIN 6(SELECT * FROM B_TABLE WHERE id = 'xxxxx') B_Table 7ON A_Table.id = B_Table.id

投稿2020/01/28 11:54

bamboo-nova

総合スコア1408

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

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

shori0128

2020/01/28 12:33

>bamboo-novaさん ご回答ありがとうございます。 上記のように記述した場合、クエリは2回発行されるのでしょうか? Rubyの記述だけ見るとそのように見えるので質問させていただきました。 ちなみに性能面だけで考えた場合、生SQLで記述した方が良いように見えるのですが、実際のところどうなのでしょうか?
bamboo-nova

2020/01/28 12:47

https://yu8mada.com/2018/05/04/ruby-s-method-chains-are-convenient-and-enjoyable/ 生のSQLでも大丈夫ですが、active recordはメソッドチェインという便利な方法を採用しているので、鎖みたいに処理を書いて、先ほどの例のようにメソッド毎に処理を分けて書くこともできるので解釈はしやすいです。また、アップグレードなどにも対応しやすいメリットもあるみたいです。 Railsのチュートリアル曰く、「クエリはその時点ではすぐに生成されず、データベースに送信されます。クエリは、データが実際に必要になった時点で初めて生成されます。」なので、データができてから随時発行される形だと思います(理解不足ですみません汗)
shori0128

2020/01/28 14:56

ご丁寧に参考URLまでありがとうございます。ActiveRecordにした時のクエリを細分化して記述するのが、クエリが分割されて発行しているように見え、性能面への影響がないのか心配してました。そのため、なんとか一文で書けないものかと四苦八苦していたところだったので、いただいたご回答で色々な疑問が解決しました! ありがとうございました!
shori0128

2020/01/28 15:39

すみません、確認できる環境がないのでこの場で質問してしまうのですが、このクエリの場合、B_tableの内容も取得できるのでしょうか? 質問ばかりで恐れ入りますが、ご回答いただけると助かります。
bamboo-nova

2020/01/28 15:53

このコードだと、BのidとAのidが一致しているAの情報を全て持ってくる感じですね...汗 すみません、ちょっと勘違いしておりました。
shori0128

2020/01/28 22:50

その場合どのような記述になるのでしょうか?ご存知でしたらご教示いただけると幸いです。
bamboo-nova

2020/01/29 01:25

よく考えると、質問のクエリって多分これ一行で大丈夫そうですね A_table.includes(:b_table).where(b_tables: { id: 'xxxxx' }) やっていること SELECT * FROM A_table LEFT OUTER JOIN b_tables ON a_table.id = b_table.id WHERE b_table.id='xxxxx'
shori0128

2020/01/29 03:49

やってみたのですが、A_tableの内容しか取得できませんでした。。 selectメソッドをチェーンして、B_tableのカラム名を明示すれば取得できたのですが、A,B両方のテーブルのカラムを取得したい場合は、select句が必要という認識になるのでしょうか?
bamboo-nova

2020/01/29 04:07

そうですね、selectやallになると思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問