通过从多个表中获取数据来生成报告

时间:2014-03-25 15:34:10

标签: ruby-on-rails activerecord ruby-on-rails-4 postgresql-9.1

我有4张桌子:

key: id, name

project: id, name

project_key: id, key_id, project_id

project_report: id, status, project_id, key_id

project_c_report: id, status, project_id, key_id, c_id

我想使用这些表生成报告: 输出应为:

Key.name, project_report.status, project_c_report.status

我能够通过从项目获取所有密钥并循环遍历

来实现此目的
array = []
project.keys.each do |k|
 p =  ProjectReport.where(keyword_id: k, project_id: p.id).map(&:status)
 c =  ProjectCReport.where(keyword_id: k, project_id: p.id, c_id:1).map(&:status)
 array << {name: k.name, pr: p, pcr: c} 
end
array

问题是我做了很多选择而且一切都很慢,有人可以用更好的方式来帮助我。

谢谢

3 个答案:

答案 0 :(得分:1)

找出数据库查询,然后直接从模型中查询数据库:

def records
  connection = ActiveRecord::Base.connection
  records = connection.select %Q {
    SELECT key.name, project_report.status, project_c_report.status
    FROM ...
    JOIN ...
    ;
  }
  records
end

答案 1 :(得分:1)

首先,在DataBase中创建一个函数。这只是一个简短的例子,也是在PostgreSQL中完成的,但不应该有太多不同 来自MySQL,SQLServer等

Function get_myreport(key_id integer, project_id integer [As many params as you'd like the function to get))

pProject    ALIAS FOR $1;
pKey        ALIAS FOR $2;

BEGIN

CREATE TEMP TABLE IF NOT EXISTS tmp_project_report(id integer, project_name character varying, *All the values you want to see in the report);
TRUNCATE tmp_project_report;

INSERT INTO tmp_project_report(all the columns)
SELECT a.table1_fields, b.table2_fields, c.table3_fields, d.table4_fields, e.table5_fields
FROM table1 a, table2 b, table3 c, table4 d, table5 e
WHERE
a.key = pKey
AND b.project_key = pProject

END;

然后,在你的控制器方法中,你可以像这样调用函数

myFunction = ActiveRecord:Base.connection.execute = "Select get_myreport("param1, param2, etc...")

您必须创建一个模型,其中放置了您所创建的temp_table上的所有字段,并且还将temp_table设置为self.table_name

然后,在您看来,您只需要对您的收藏进行迭代并相应地显示值

@report = TempTable.all

<% @report.each_do |report| %>
  <% report.value1 %>
  <% etc... %>
<% end %>

答案 2 :(得分:1)

如果您选择将其保留在Rails中,可以尝试以下内容(请注意,以下查询未经测试且仅针对概念显示):

report_data = Project.joins(project_key: :key)
  .joins('left join project_reports on project_keys.project_id = project_reports.project_id and project_keys.key_id = project_reports.key_id 
          left join project_c_reports on project_keys.project_id = project_c_reports.project_id and project_keys.key_id = project_c_reports.key_id')
  .where('project_c_reports.c_id = ?', 1)
  .select('projects.name, project_reports.status as report_status, project_c_reports.status as c_report_status')

这应该为您提供一组Project个对象,每个对象包含所选的三个属性name, report_status, c_report_status。要在这三个元素的数组中获取这些值,您可以这样做:

report_data.map { |p| [ p.name, p.report_status, p.c_report_status ] }

查询的连接类型取决于您的要求。鉴于索引已经到位,查询应该与它在代码中的外观相比更好!