ruby-on-rails 如何带条件的左外联接

bhmjp9jg  于 2023-05-23  发布在  Ruby
关注(0)|答案(4)|浏览(211)

我有这样的关系:

class Action < ApplicationRecord
   has_many :actions_users

我试着做了一个类似的查询:

select *
from actions left outer join actions_users
on actions_users.action_id = actions.id and actions_users.user_id = 1
where actions.user_id = 1

同时,根据我的经验,在我尝试的所有结果中,

select *
from actions left outer join actions_users
on actions_users.action_id = actions.id
where actions.user_id = 1 and actions_users.user_id = 1

连接条件代码和一般条件在where函数中。
我怎么才能算出来呢?

ylamdve6

ylamdve61#

您可以在join query中传递一个字符串,并为此使用rails表命名约定。

Action.joins("left outer join action_users on (action_users.id = actions.id and action_users.id = 1")).where('action_users.user_id = ? ', 1)
6l7fqoea

6l7fqoea2#

在Rails 7之前,无法直接在OUTER JOIN上指定条件,请参阅在连接表上指定条件的文档。所示的示例适用于INNER JOIN s(因为它们使用.where),但出于同样的原因,不适用于OUTER JOIN s。
您可以尝试手动指定OUTER JOIN,但在传递参数时会遇到问题:

Action.joins("LEFT OUTER JOIN action_users ON (action_users.id = actions.id AND action_users.user_id = :user_id")

因此,您需要像这样执行参数替换:

outer_join_sanitized = ApplicationRecord.sanitize_sql([
  "LEFT OUTER JOIN action_users ON (action_users.id = actions.id AND action_users.user_id = :user_id)", 
  { user_id: 22 }
])

然后你可以使用Actions.joins(outer_join_sanitized)。此时,您可能会同意,从一开始就使用原始SQL运行是更简单的方法。

tnkciper

tnkciper3#

Action.left_outer_joins(:actions_users).where(user_id: 1)

select *
from actions left outer join actions_users
on actions_users.action_id = actions.id and actions_users.user_id = 1
where actions.user_id = 1

虽然你还没有要求...

Action.left_outer_joins(:actions_users).where(actions_users: {status: 'active'})

select *
from actions left outer join actions_users
on actions_users.action_id = actions.id and actions_users.user_id = 1
where actions_users.status = 'active'
db2dz4w8

db2dz4w84#

因为有一个通用的where条件,所以可以使用includes。这将生成一个LEFT OUTER JOIN查询:

Action.includes(:actions_users).where(actions_users: { user_id: true })

或者,如果您使用的是Rails 5+,Active Record提供了一个finder方法left_outer_joins

Action.left_outer_joins(:actions_users).where(actions_users: { user_id: true })

相关问题