1

我正在使用 Ruby on Rails 2.3.5 从我的 SQLite 数据库中接收一组模型。目前我正在使用子查询来选择我真正想要的那些:

find(:all, 
  :conditions => "foo.id in (
                    SELECT bar.foo_id FROM bar
                    JOIN baz
                      ON baz.bar_id = bar.id
                    WHERE baz.bla in (1, 2, 3)
                  )"
)

我知道这很愚蠢,因为子查询为每一行评估相同的结果,我猜 SQLite 不够聪明,无法注意到它可以被优化。所以我想把它从查询中删除。我知道我可以简单地使用第二个从 Rails 调用它find(),但是考虑到子查询的返回值可能会变得比较大,我想在数据库中做所有事情,所以我不需要在数据库和 Rails。

那么,我该如何做模型find()并告诉它,它应该查找我的实际子查询的返回值,然后使用它的结果来比较我的其他行?我可以通过一次调用将其传递给find()SQLite 吗?

4

3 回答 3

0

通常,您应该尝试在模型中定义您的关系。这样你就可以轻松使用 ActiveRecord 的助手

class Foo < ActiveRecord::Base
  self.table_name = "foo"

  has_many :bars
end

class Bar < ActiveRecord::Base
  self.table_name = "bar"

  belongs_to :foo
  has_many :bazs
end

class Baz < ActiveRecord::Base
  self.table_name = "baz"

  belongs_to :bar
end

有了这些模型,您可以编写类似于以下内容的查询:

Foo.find(:all, :include => {:bar => :baz}, :conditions => ["#{Baz.table_name}.id IN (?)", [1,2,3]])
于 2012-05-23T17:54:32.327 回答
0

给定以下模型:

class Foo < ActiveRecord::Base
  has_many :bars
  has_many :bazs, :through => :bars

  attr_accessible :title
end


class Bar < ActiveRecord::Base
  belongs_to :foo
  has_many :bazs

  attr_accessible :title
end


class Baz < ActiveRecord::Base
  belongs_to :bar

  attr_accessible :title
end

你可以:

Foo.all(
  :joins => { :bars => :bazs },
  :conditions => { :bars => { :bazs => { :id => [1000] } } }
)

1000您感兴趣的 Baz 的 id 在哪里。

这将生成以下 SQL:

SELECT "foos".* FROM "foos" INNER JOIN "bars" ON "bars"."foo_id" = "foos"."id" INNER JOIN "bazs" ON "bazs"."bar_id" = "bars"."id" WHERE "bazs"."id" IN (1000)

如果你这样做是一样的:

Foo.all(
  :joins => { :bars => :bazs },
  :conditions => { :bazs => { :id => [1000] } }
)

甚至更好,使用through关联:

Foo.all(
  :joins => [:bazs],
  :conditions => { :bazs => { :id => [1000] } }
)

结果将是符合该条件的所有 Foo 记录,并且 SQL 将是相同的。

希望这能回答你的问题。

于 2012-05-24T13:48:14.383 回答
0

我想知道您是否可以执行以下操作:

    subs = connection.select_rows("SELECT bar.foo_id FROM bar
                                   JOIN baz
                                   ON baz.bar_id = bar.id
                                   WHERE baz.bla in (1, 2, 3)")
    find(:all, :conditions => "foo.id in (#{subs.join(',')})")

这就是我试图在 Rails 3 中重写的内容。

于 2012-05-23T17:33:34.813 回答