我有一个rails应用程序:
user has_many :projects
user has_many :tasks, :through => :projects
project has_many :tasks
每项任务都有里程碑日期。
要显示项目详细信息表,其中包含我正在使用的下一个里程碑日期:
@projects = current_user.tasks.joins(:project).select("distinct on (projects.id) projects.*, tasks.*").reorder("projects.id, tasks.milestone ASC")
这很好用。
我现在希望能够对表格列进行排序。
根据Postgres DISTINCT ON
不可排序,您必须将其包装在另一个select语句中,即SELECT * FROM (SELECT DISTINCT ON....) ORDER BY column_3
我确实认为订购的列可以根据需要在SQL中使用,即(按项目名称DESC排序):
@projects = current_user.tasks.joins(:project).select("distinct on (projects.name) projects.*, tasks.*").reorder("projects.name DESC, tasks.milestone ASC")
哪个有效,但我也希望能够通过里程碑订购,但这不会那样。
有人可以告诉我如何转换我的rails查询,以便可以通过任何列进行排序吗?
更新
我想我的问题只是如何在周围的SELECT
和ORDER BY
中包装一个activerecord查询?
我想我已经成功实现了它:
inner_query = current_user.tasks.select("distinct on (projects.id) projects.*, tasks.*").reorder("projects.id, tasks.milestone ASC").to_sql
@projects = Task.paginate_by_sql("select * from (#{inner_query}) as user_projects order by user_projects.name", :page => params[:page])
这是最好的方式还是有人能想到更好的方法? - find / paginate_by_sql似乎是一种解决方法,我宁愿保持在activerecord查询的范围内。
由于
答案 0 :(得分:5)
您正在尝试获取一组项目,但是您从current_user.tasks
开始。
为什么不从current_user.projects
开始,这保证了不同的项目?
@projects = current_user.projects.includes(:tasks).order("projects.name, tasks.milestone")
替代答案
@projects = current_user.projects.joins(:tasks).select('projects.*, min(tasks.milestone) as next_milestone').order('projects.name').group('projects.id')
@projects.each{|p| puts "#{p.name} #{p.next_milestone}"}
这将为每个项目提供一行,计算出最小tasks.milestone值,可通过next_milestone在项目行结果中访问。没有额外的任务记录,只是下一个里程碑日期。
答案 1 :(得分:1)
在用户控制器中:
inner_query = current_user.tasks.next.to_sql
@projects = Task.paginate_by_sql("select * from (#{inner_query}) as user_projects order by user_projects.#{sort_column} #{sort_direction}", :page => params[:page])
在任务模型中:
scope :next, select("distinct on (projects.id) projects.*, tasks.*").reorder("projects.id, tasks.milestone ASC")
这种方式使用postgres的强大功能只返回必要的记录,使记录集更小,更容易使用,但权衡的是RoR代码看起来不像Carlos Drew那样具有吸引力或可读性。建议。
答案 2 :(得分:0)
回答这个问题:
我想我的问题只是如何在周围的SELECT和ORDER B中包装一个activerecord查询
自ActiveRecord 4.0.2起,现在有php.ini
。
使用模型的示例:
<model>.from
您可以将其打包在inner_query = Project.joins(:tasks).select("DISTINCT ON (projects.id), *") // SELECT DISTINCT ON (projects.id) FROM projects INNER JOIN tasks ON tasks.project_id = projects.id;
:
from