Tengo el siguiente código:
@posts = Post.joins(:user).joins(:blog).select
que está destinado a encontrar todas las publicaciones y devolverlas y los usuarios y blogs asociados. Sin embargo, los usuarios son opcionales, lo que significa que el INNER JOINque :joinsgenera no devuelve muchos registros.
¿Cómo utilizo esto para generar un LEFT OUTER JOINen su lugar?
ruby-on-rails
ruby
activerecord
Neil Middleton
fuente
fuente

Respuestas:
@posts = Post.joins("LEFT OUTER JOIN users ON users.id = posts.user_id"). joins(:blog).selectfuente
@posts = Post.joins("LEFT OUTER JOIN users ON users.id = posts.user_id").joins(:blog).where("users.id IS NULL").selectselect('posts.*')?Puede hacer con esto
includescomo se documenta en la guía Rails :Post.includes(:comments).where(comments: {visible: true})Resultados en:
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)fuente
includesno hace una combinación, sino una consulta separada para obtener la asociación. Por lo tanto, evita N + 1, pero no de la misma manera que JOIN, donde los registros se obtienen en una consulta.includesfunción hace ambas cosas, dependiendo del contexto en el que la esté utilizando. La guía Rails lo explica mejor que yo si leyera la sección 12 completa: guides.rubyonrails.org/ …includesgenerará 2 consultas en lugar de unaJOINsi no necesita elWHERE.references(:comments). Además, esto hará que todos los comentarios devueltos se carguen ansiosamente en la memoria debido aincludesque posiblemente no sea lo que desea.Post.includes(:comments).where(comments: {visible: true}). De esta manera tampoco es necesario usarreferences.Soy un gran admirador de la joya squeel :
Es compatible con ambos
innery seouterune, así como la capacidad de especificar una clase / tipo para las relaciones polimórficas pertenecen a.fuente
Utilizar
eager_load:@posts = Post.eager_load(:user)fuente
De forma predeterminada, cuando pasa
ActiveRecord::Base#joinsuna asociación con nombre, realizará una INNER JOIN. Tendrá que pasar una cadena que represente su LEFT OUTER JOIN.De la documentación :
fuente
Hay una left_outer_joins método en el activerecord. Puedes usarlo así:
@posts = Post.left_outer_joins(:user).joins(:blog).selectfuente
Buenas noticias, Rails 5 ahora es compatible
LEFT OUTER JOIN. Su consulta ahora se vería así:@posts = Post.left_outer_joins(:user, :blog)fuente
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")fuente