私は次のコードを持っています:
@posts = Post.joins(:user).joins(:blog).select
これは、すべての投稿を検索し、それらと関連するユーザーおよびブログを返すことを目的としています。ただし、ユーザーはオプションです。つまり、INNER JOIN
、:joins
生成大量のレコードを返しません。
これを使用してLEFT OUTER JOIN
代わりに生成するにはどうすればよいですか?
回答:
@posts = Post.joins("LEFT OUTER JOIN users ON users.id = posts.user_id").
joins(:blog).select
@posts = Post.joins("LEFT OUTER JOIN users ON users.id = posts.user_id").joins(:blog).where("users.id IS NULL").select
select('posts.*')
か?
includes
Railsガイドに記載されているようにこれを使用できます。
Post.includes(:comments).where(comments: {visible: true})
結果:
SELECT "posts"."id" AS t0_r0, ...
"comments"."updated_at" AS t1_r5
FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id"
WHERE (comments.visible = 1)
includes
は、結合は行いませんが、関連付けを取得するための個別のクエリを実行します。したがって、N + 1を回避しますが、レコードが1つのクエリでフェッチされるJOINと同じ方法ではありません。
includes
関数は、使用しているコンテキストに応じて両方を実行するため、注意が必要です。Rails
includes
は、の代わりに2つのクエリが生成されるため、これは質問に部分的にしか答えJOIN
ませんWHERE
。
references(:comments)
。さらに、これにより、返されるすべてのコメントがメモリに熱心にロードされますincludes
。これは、おそらくあなたが望むものではありません。
Post.includes(:comments).where(comments: {visible: true})
。このように、を使用する必要もありませんreferences
。
私はの大ファンです squeelgemの:
Post.joins{user.outer}.joins{blog}
inner
とouter
結合の両方をサポートし、ポリモーフィックなbelongs_to関係のクラス/タイプを指定する機能もサポートします。
デフォルトではActiveRecord::Base#joins
、名前付きアソシエーションを渡すと、内部結合が実行されます。LEFT OUTERJOINを表す文字列を渡す必要があります。
ドキュメントから:
:joins
-"LEFT JOIN comments ON comments.post_id = id
"(めったに必要ありません)のような追加の結合用のSQLフラグメント、またはに使用されるのと同じ形式の名前付き関連付け:include
オプションにられたテーブルでINNER JOINを実行するか、両方の文字列の混合を含む配列のいずれかです。と名前付きの関連付け。値が文字列の場合、レコードにはテーブルの列に対応しない属性があるため、レコードは読み取り専用で返されます。
:readonly => false
オーバーライドするために渡し ます。
activerecordにはleft_outer_joinsメソッドがあります。次のように使用できます。
@posts = Post.left_outer_joins(:user).joins(:blog).select
class User < ActiveRecord::Base
has_many :friends, :foreign_key=>"u_from",:class_name=>"Friend"
end
class Friend < ActiveRecord::Base
belongs_to :user
end
friends = user.friends.where(:u_req_status=>2).joins("LEFT OUTER JOIN users ON users.u_id = friends.u_to").select("friend_id,u_from,u_to,u_first_name,u_last_name,u_email,u_fbid,u_twtid,u_picture_url,u_quote")