【发布时间】:2017-03-02 12:56:57
【问题描述】:
我有一个系统和一个报告模型。系统 has_many 报告和报告属于_to 系统。每个每日报告由每个系统的 175 条记录组成。
我需要在我的 system#index 页面上进行查询,该页面应列出在最近创建报告时过滤的所有系统。这是我的第一次尝试。
@systems = System.joins('LEFT JOIN reports ON reports.system_id = systems.id').group('systems.id').order('MAX(reports.created_at) ASC')
这列出了带有报告(系统负载(2.1 毫秒))但按 system_id 而非报告 created_at 排序的系统。
第二次尝试
@systems = System.joins(:reports).where("reports.created_at = (SELECT MAX(created_at) FROM reports p group by system_id having p.system_id = reports.system_id)").order('reports.created_at DESC')
尽管在 report.created_at 上有索引,但这个查询确实很慢(系统负载(546.2 毫秒))。
第三次尝试
@systems = System.joins(:reports).where("reports.id = (SELECT MAX(id) FROM reports p group by system_id having p.system_id = reports.system_id)").order('reports.id DESC')
也完成了这项工作,比第二次尝试(系统负载(468.3ms))略快,但仍然不够快。
有什么建议吗?
编辑 03032017
我在一个小型测试数据集上做了数字
旧查询
SELECT s.* FROM systems s
JOIN reports r ON r.system_id = s.id
WHERE r.created_at = (
SELECT MAX(created_at)
FROM reports p
group by p.system_id
having p.system_id = r.system_id)
ORDER BY r.id DESC
Time: 622.683 ms
Philip Couling 解决方案(干净,只返回带有报告的系统)
SELECT systems.*
FROM systems
JOIN (
SELECT reports.system_id
, MAX(reports.created_at) created
FROM reports
GROUP BY reports.system_id
) AS r_date ON systems.id = r_date.system_id
ORDER BY r_date.created;
Time: 1.434 ms
BookofGreg 解决方案(会给我所有系统,报告或不报告)
select systems.* from systems order by updated_at;
Time: 0.253 ms
我无法使用 systemjack 的解决方案。
最快的解决方案:bookofgreg
最干净的解决方案:philip couling
感谢您的意见。
【问题讨论】:
标签: ruby-on-rails postgresql activerecord