web-dev-qa-db-ja.com

Rails ActiveRecordを使用してLEFT OUTER JOINを実行するにはどうすればよいですか?

アイデアはありません。手がかり(参考サイトなど)を教えてもらえますか?どんな助けでもありがたいです。

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

予期されるSQLステートメント:

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

以下の関連付けを設定しようとしましたが、この後どうすればよいかわかりません。

class Group < ActiveRecord::Base
  has_many :user_group_cmb
end

class UserGroupCmb < ActiveRecord::Base
  has_many :group
end

Railsバージョン:3.1.1

21
zono

includesLEFT OUTER JOINincludesアソシエーションが使用するテーブルで条件を実行する場合、クエリを実行します。

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

Rails 5以降では、次のことが可能です。

Group.left_outer_joins(:user_group_cmb)

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

16
Diego Plentz

テーブルを参照しているかどうかに関係なく、Rails 3.xでこれを行うことができます:where句で:

Group.eager_load(:user_group_cmb)

...そして、それは左外部結合を実行します

10
knoopx

includesを使用する には望ましくない副作用がある可能性があることに言及することは非常に重要です。

フィルタリングされた関連付けがその後スコープされる場合、元のフィルタリングのすべてが消えます

結局のところ、フィルターされた関連付けにスコープを設定することで、インクルードから得られた副作用としてのフィルタリングをすべて失いました。また、検索方法のせいでもありません。

記事全体を必ずお読みください。代わりに そのための宝石 があります。

8
user191766

カスタム結合ステートメントを使用します。

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

受け入れられた回答の問題は、実際にLEFT INNER JOIN技術的には、user_group_cmbs. user_idはnullです(これがLEFT OUTER JOIN)。

実用的な解決策は #references

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

またはさらに便利 #eager_load

Group.eager_load(:user_group_cmb)

より詳細な説明 こちら をお読みください。

6
KARASZI István

ユーザーをグループにリンクするだけの場合は、 has_and_belongs_to_many を使用します。追加のメンバーシップ情報を保存する必要がある場合は has_many:through を使用します。

例:

class User < ActiveRecord::Base
  has_and_belongs_to_many :groups
end

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

私は50の評判を持っていないので、以前の答えにコメントできませんでした。しかし、私が以下のエラーに遭遇したとき、それは私にとってどのように機能したかです

インクルード参照リレーションは、StatementInvalid例外を発生させ、FROM句のエントリを見逃していると警告します。 joinへの明示的な呼び出しを追加する必要があります。これはデフォルトで内部になっています。

私は.referencesを使用してテーブル名を言及する必要がありました、またはそれがFROM句に追加されました

0
Raja