web-dev-qa-db-fra.com

Comment puis-je faire un LEFT OUTER JOIN en utilisant Rails ActiveRecord?

Je n'ai aucune idée. Pourriez-vous me donner des indices (comme des sites de référence). Toute aide serait appréciée.

Model1: GROUP(id, name)
Model2: USER_GROUP_CMB(id, user_id, group_id)

Déclaration SQL attendue:

SELECT * 
FROM groups AS g LEFT OUTER JOIN user_group_cmbs AS cmb 
            ON g.id = cmb.group_id
WHERE cmb.user_id = 1

J'ai essayé de créer des associations ci-dessous mais je ne sais pas quoi faire après cela.

class Group < ActiveRecord::Base
  has_many :user_group_cmb
end

class UserGroupCmb < ActiveRecord::Base
  has_many :group
end

Rails Version: 3.1.1

19
zono

Je crois qu'une includes utilisera une requête LEFT OUTER JOIN si vous créez une condition sur la table que l'association includes utilise:

Group.includes(:user_group_cmb).where(user_group_cmbs: { user_id: 1 })
32
Ryan Bigg

Rails 5+ vous permet d'effectuer les tâches suivantes:

Group.left_outer_joins(:user_group_cmb)

http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-left_joins

14
Diego Plentz

Vous pouvez le faire dans Rails 3.x, que vous référeniez la table ou non, dans une clause where:

Group.eager_load(:user_group_cmb)

... et il effectuera une jointure externe gauche

10
knoopx

Il peut être très important de mentionner que l’utilisation inclut a peut-être des effets secondaires indésirables.

si l'association filtrée est ensuite étendue, tout le filtrage d'origine disparaît

En fin de compte, en ciblant l’association filtrée, nous avons perdu l’effet De filtrage en tant qu’effet indésirable que nous avons obtenu à partir d’inclusions. Et ce n’est pas À cause de la façon dont nous avons cherché.

Assurez-vous de lire l'article complet et alternativement il y a un bijou pour cela .

8
user191766

Utilisez une déclaration de jointure personnalisée:

Group.joins("left outer join user_group_cmbs as cmb on groups.id = cmb.group_id")
  .where("cmb.user_id = ?", 1)
7
hammady

Le problème avec la réponse acceptée est qu’il effectuera un LEFT INNER JOIN techniquement car il n’affiche pas les entrées où le user_group_cmbs. user_id est nul (ce qui serait la raison de faire un LEFT OUTER JOIN).

Une solution efficace consiste à utiliser #references :

Group.includes(:user_group_cmb).references(:user_group_cmb)

Ou encore plus pratique #eager_load :

Group.eager_load(:user_group_cmb)

Lisez l'explication plus détaillée ici .

6
KARASZI István

Utilisez has_and_belongs_to_many si vous avez juste besoin de lier des utilisateurs à des groupes. Utilisez has_many: through si vous devez stocker des informations supplémentaires sur les membres.

Exemple:

class User < ActiveRecord::Base
  has_and_belongs_to_many :groups
end

class Group < ActiveRecord::Base
  has_and_belongs_to_many :users      
end
2
panupan

Je ne peux pas commenter une réponse précédente car je n’ai pas 50 points de réputation.

la relation includes-référencé déclenche une exception StatementInvalid, en se plaignant du manque d'une entrée de la clause FROM. Je dois ajouter un appel explicite à rejoindre, qui est par défaut interne. 

Je devais utiliser .references et mentionner le nom de la table ou être ajouté à la clause FROM

0
Raja