19

我有一个 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")

这工作正常。

我现在希望能够对表格列进行排序。

根据 PostgresDISTINCT 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")

这可行,但我也希望能够按里程碑订购,但那样行不通。

有人能告诉我如何转换我的 rails 查询,以便它可以按任何列排序吗?

更新


我想我的问题只是如何将 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])

这是最好的方法还是有人能想到更好的方法?- find/paginate_by_sql 似乎是一种解决方法,我更愿意留在 activerecord 查询的范围内。

谢谢

4

3 回答 3

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 在项目行结果中访问。没有额外的任务记录,只是下一个里程碑日期。

于 2013-06-25T17:59:00.673 回答
2

在用户控制器中:

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

于 2013-07-03T21:11:52.427 回答
2

要回答这个问题:

我想我的问题只是如何将 activerecord 查询包装在周围的 SELECT 和 ORDER 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)
于 2018-02-13T04:45:49.203 回答