需要帮助将SQL查询转换为ActiveRecord查询

时间:2011-09-07 14:34:44

标签: mysql sql ruby-on-rails ruby-on-rails-3

我有以下SQL代码:

SELECT u.full_name, pu.task_name, sum(hours) 
FROM efforts
INNER JOIN project_tasks pu ON efforts.project_task_id = pu.id   
INNER JOIN users u ON efforts.user_id = u.id 
GROUP BY user_id, task_name

输出所有用户,他们的任务和工作时间。我现在要做的是将其转换为Rails的ActiveRecord查询。

我试图让它看起来与我在下面所做的相似,但似乎无法使我的逻辑正确。

    Project.all.each do |project|
      projdata = { 'name' => project.project_name.to_s,
                  'values' => [] }

    ['Pre-Sales','Project','Fault Fixing','Support'].each do |taskname|

     record = Effort.sum( :hours,
                          :joins => :project_task,
                           :conditions => { "project_tasks.project_id" => project.id,
                                         "project_tasks.task_name" => taskname } )             
        projdata[ 'values' ].push( record )
      end

      @data.push( projdata )
    end
  end
end 

添加了图片链接

Link to image

该链接说明了一个图表。我需要做的是将我的SQL语句转换为activeRecord查询,它将像我提供的其他图形一样显示它。

3 个答案:

答案 0 :(得分:0)

SELECT u.full_name, pu.task_name, hours 
FROM efforts
INNER JOIN project_tasks pu ON efforts.project_task_id = pu.id   
INNER JOIN users u ON efforts.user_id = u.id 
GROUP BY user_id, task_name

Effort.find(:all, :select => "users.full_name, project_tasks.task_name, hours", :joins => [:user, :project_task], :group => "users.user_id, project_tasks.task_name")

但是,我有一个疑问,你怎么能得到“小时”字段而不在分组部分添加它。所以,最好的是,您也可以在分组部分添加小时数。

但是,您应该在以下文件中进行一些其他更改

供应商/插件/ expandjoinquery / init.rb”

class ActiveRecord::Base
  class << self
    private
    def add_joins!(sql, options, scope = :auto)
      scope = scope(:find) if :auto == scope
      join = (scope && scope[:joins]) || options[:joins]
      sql << " #{expand_join_query(join)} " if join
    end

    def expand_join_query(*joins)
      joins.flatten.map{|join|
        case join
        when Symbol
          ref = reflections[join] or
            raise ActiveRecord::ActiveRecordError, "Could not find the source association :#{join} in model #{self}"
          case ref.macro
          when :belongs_to
            "INNER JOIN %s ON %s.%s = %s.%s" % [ref.table_name, ref.table_name, primary_key, table_name, ref.primary_key_name]
          else
            "INNER JOIN %s ON %s.%s = %s.%s" % [ref.table_name, ref.table_name, ref.primary_key_name, table_name, primary_key]
          end
        else
          join.to_s
        end
      }.join(" ")
    end
  end
end

参考:http://snippets.dzone.com/posts/show/2119

我的建议是,为什么要使用带有关联名称的预先加载?。

答案 1 :(得分:0)

尝试类似:

Effort.joins(:project_tasks, :user).select("sum(hours) as total_hours, users.full_name, project_tasks.task_name").group("users.user_id, project_tasks.task_name")

答案 2 :(得分:0)

试试这个:

Effort.select(
   "users.full_name        full_name, 
    project_tasks.task_name       task_name, 
    SUM(efforts.hours) total_hours").
  joins(:project_task, :user).
  group("users.user_id, users.full_name, project_tasks.task_name").map do |e|
  puts e.full_name, e.task_name, e.total_hours
end