【问题标题】:How can I get this complicated query to work with ActiveRecord?如何让这个复杂的查询与 ActiveRecord 一起使用?
【发布时间】:2012-03-07 05:12:17
【问题描述】:

我有一个复杂的 SQL 查询,涉及 3 个模型,根据时间操作创建虚拟属性...理想情况下,我想使用 ActiveRecord 等方法来生成它,这样它会更好,但我不知道怎么做。

  find_by_sql <<--sql
    SELECT username, count(*) as records, AVG(time_taken) as time_taken
    FROM (
      SELECT TIMESTAMPDIFF(HOUR, posts.created_at, reports.created_at) as time_taken,
             users.username as username
      FROM reports, users, posts
      WHERE reports.user_id = users.id AND 
            reports.post_id = posts.id
    ) AS dashboard_data # this name is unused, but apparently required
    GROUP BY username
  sql

有没有办法在 ActiveRecord 中做这样的事情?还是原始 sql 是做这种复杂事情的唯一方法?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 activerecord


    【解决方案1】:

    除非它来自一张桌子,否则你会被困在做这样的事情。您正在从一个超出 ActiveRecord 预期范围的子查询中获取。 ORM 旨在将对象映射到定义明确的表中的特定行。

    您有时可以伪造它,以便您所做的任何事情看起来都像表格一样,可以通过使用 SQL 视图来工作。如果 ActiveRecord 可以像表格一样进行查询,它将很乐意使用视图。例如,如果它定义了一个id 列作为某种主键,它应该可以工作。在您的情况下,您可以GROUP BY users.id 并暴露users.id AS id 以及users.username

    【讨论】:

      【解决方案2】:

      我认为这相当于你正在做的事情:

      User.joins({:reports=>:posts}).
           group("users.username").
           select("users.username, 
                   count(*) as records,
                   avg(timestampdiff(hour, posts.created_at, reports.created_at)) as time_taken")
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-15
        相关资源
        最近更新 更多