1

如何使用 ActiveRecord 查询选择与某个父表对应的所有子行。

create table foo (id, ...)
create table bar (id, foo_id, ...)

select * from foo where key = ? 
# The above return a single row or multiple rows.

select * from bar where foo_id in <ids from the above output>

我如何实现这一目标?

4

4 回答 4

1

仅使用查询ActiveRecord

foo = Foo.where(:key = ?)
Bar.where(:foo_id => foo)

使用关联和急切加载

#foo model
class Foo < ActiveRecord::Base
  has_many :bars
end

#bar model
class Bar < ActiveRecord::Base
 belongs_to :foo
end

#query
Foo.includes(:bars).where(:key => ?).collect(&:bars)
于 2013-01-02T17:11:28.393 回答
0

嗯...我不知道您的问题是否可以用 ARel 完成类似的事情(它不能)。您想要的是使用子查询提供匹配,您可以在 SQL 中执行此操作,因此使用 ActiveRecord::Base.find_by_sql。

ActiveRecord::Base.find_by_sql("select * from bar where foo_id in 
(select id from foo where key = #{key})")
于 2013-01-02T17:09:48.060 回答
0

Arel会这样做

Profile.where(user_id: User.select("id").where(exclude_from_analytics: true))
#=> Profile Load (395.1ms)  SELECT `profiles`.* FROM `profiles` WHERE `profiles`.`user_id` IN (SELECT id FROM `users` WHERE `users`.`exclude_from_analytics` = 1)

您是否真的要进行子选择是另一回事 - 值得尝试将查询编写为连接:

Bar.joins(:foo).where(:foos => {:key => key})

假设您已设置 Bar 与belongs_to :foo关联。joins 方法也将接受一个原始的 sql 片段

于 2013-01-02T17:14:29.020 回答
0

你应该能够做到

Bar.find_all_by_foo_id([1,2,3,4])

在这种情况下,您必须先找到所有 foo id。但是,如果您在 ChuckE 提到的一个查询子查询中需要它是最好的。

于 2013-01-02T17:17:32.103 回答