以正确的方式从ruby执行查询

时间:2013-02-22 08:23:10

标签: ruby-on-rails ruby

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

现在我正在尝试从数据库中获取一些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 manager执行此查询时,这会给我1000个ID。我想先获取id列表然后按id找到对象。

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

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

2 个答案:

答案 0 :(得分: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命令,并可能有助于您的调试。

答案 1 :(得分: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注入潜力。