3

我刚开始使用 ruby​​ on rails 并且有一个关于更复杂查询的问题。到目前为止,我在查看 rails guide 时完成了简单的查询,并且效果非常好。

现在我正在尝试从数据库中获取一些 Id,我会使用这些 Id 来获取真实的对象并对它们做一些事情。获得这些比简单的 Object.find 方法要复杂一些。

这是我的查询的样子:

select * from quotas q, requests r
where q.id=r.quota_id
and q.status=3
and r.text is not null
and q.id in
(
select A.id from (
select max(id) as id, name 
from quotas
group by name) A
)
order by q.created_at desc
limit 1000;

从 sql 管理器执行此查询时,这会给我 1000 个 id。我想先获取 id 列表,然后按 id 查找对象。

有没有办法通过使用这个查询直接获取这些对象?避免 ids 查找?我用谷歌搜索你可以执行这样的查询:

ActiveRecord::Base.connection.execute(query);
4

2 回答 2

3

假设Quota has_many :requests,

Quota.includes(:requests).
  where(status:3).
  where('requests.text is not null').
  where("quotas.id in (#{subquery_string_here})").
  order('quotas.created_at desc').limit(1000)

我绝不是专家,但大多数基本的 SQL 功能都包含在 ActiveRecord 中。您可能还想查看#group#pluck方法来消除丑陋的字符串子查询。

调用#to_sql关系对象将向您显示它等效的 SQL 命令,并且可能有助于您的调试。

于 2013-02-22T08:33:16.897 回答
0

我会为此使用 find_by_sql 。我不会发誓这是完全正确的,但我记得你几乎可以将 SQL 语句插入 find_by_sql 并且结果列将作为你调用它的类的对象数组的属性返回:

  status = 3
  Quota.find_by_sql('
    select * 
    from quotas q, requests r
    where q.id=r.quota_id
    and q.status= ?
    and r.text is not null
    and q.id in
    (
      select A.id from (
      select max(id) as id, name 
      from quotas
      group by name) A
    )
    order by q.created_at desc
    limit 1000;', status)

如果您以习惯于编写原始 SQL 的身份来到 Rails,那么使用这种语法可能比将一堆 ActiveRecord 方法串在一起更好——结果是一样的,所以这只是您发现什么更具可读性的问题。

顺便说一句,您不应该在 SQL 查询中使用字符串插值(即 #{variable} 语法)。使用 '?' 代替语法(参见我的示例)以避免 SQL 注入的可能性。

于 2013-02-22T09:53:04.043 回答