使用轨道"DISTINCT ON"对 postgres 应用不同的顺序



我有一个铁路应用:

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 * 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")

哪个有效,但我也希望能够按里程碑订购,而这是不起作用的。

有人可以告诉我如何转换我的导轨查询,以便任何列可以订购它?

更新


我想我的问题只是如何将ActivereCord查询包装在周围的SELECTORDER BY

我认为我已经设法实现了:

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])

这是最好的方法,还是有人可以想到更好的方法? - 查找/paginate_by_sql似乎是一个解决方法,我宁愿留在Activerecord查询的领域中。

谢谢

您正在尝试获取一组项目,但您是从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}"}

,将为您提供每个项目的一行,并具有计算的最小任务。米勒斯通值,可通过next_milestone在项目行结果上访问。没有额外的任务记录,只是下一个里程碑日期。

在用户控制器中:

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的诱人或可读性那样诱人或可读性建议。

回答这个问题:

我想我的问题只是如何将ActivereCord查询包装在周围的选择和顺序B

由于ActivereCord 4.0.2现在有<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中:

sorted_query = Project.from(inner_query, :projects).order(:name)

相关内容

最新更新