Saya memiliki kode berikut:
@posts = Post.joins(:user).joins(:blog).select
yang dimaksudkan untuk menemukan semua kiriman dan mengembalikannya serta pengguna dan blog terkait. Namun, pengguna bersifat opsional yang berarti bahwa INNER JOIN
yang :joins
menghasilkan tidak mengembalikan banyak catatan.
Bagaimana cara menggunakan ini untuk menghasilkan sebagai LEFT OUTER JOIN
gantinya?
ruby-on-rails
ruby
activerecord
Neil Middleton
sumber
sumber
Jawaban:
@posts = Post.joins("LEFT OUTER JOIN users ON users.id = posts.user_id"). joins(:blog).select
sumber
@posts = Post.joins("LEFT OUTER JOIN users ON users.id = posts.user_id").joins(:blog).where("users.id IS NULL").select
select('posts.*')
?Anda dapat melakukan ini dengan
includes
seperti yang didokumentasikan di panduan Rails :Post.includes(:comments).where(comments: {visible: true})
Hasil dalam:
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)
sumber
includes
tidak melakukan join, tetapi query terpisah untuk mendapatkan assosiation. Jadi ini menghindari N + 1, tetapi tidak dengan cara yang sama seperti JOIN di mana rekaman diambil dalam satu kueri.includes
fungsinya melakukan keduanya, tergantung pada konteks tempat Anda menggunakannya. Panduan Rails menjelaskannya lebih baik daripada yang saya bisa jika Anda membaca keseluruhan bagian 12: Guideline.rubyonrails.org/ …includes
akan menghasilkan 2 query, bukan sebuahJOIN
jika Anda tidak membutuhkanWHERE
.references(:comments)
. Selain itu, ini akan menyebabkan semua komentar yang dikembalikan ingin dimuat dalam memori karenaincludes
, yang mungkin bukan yang Anda inginkan.Post.includes(:comments).where(comments: {visible: true})
. Dengan cara ini Anda juga tidak perlu menggunakanreferences
.Saya penggemar berat squeel gem :
Ini mendukung keduanya
inner
danouter
bergabung, serta kemampuan untuk menentukan kelas / tipe untuk hubungan milik_to polimorfik.sumber
Penggunaan
eager_load
:@posts = Post.eager_load(:user)
sumber
Secara default ketika Anda melewati
ActiveRecord::Base#joins
asosiasi bernama, itu akan melakukan INNER JOIN. Anda harus melewatkan string yang mewakili LEFT OUTER JOIN Anda.Dari dokumentasi :
sumber
Ada metode left_outer_joins di activerecord . Anda bisa menggunakannya seperti ini:
@posts = Post.left_outer_joins(:user).joins(:blog).select
sumber
Kabar baiknya, Rails 5 sekarang mendukung
LEFT OUTER JOIN
. Kueri Anda sekarang akan terlihat seperti ini:@posts = Post.left_outer_joins(:user, :blog)
sumber
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")
sumber