【问题标题】:Rails: Group By join tableRails:按联接表分组
【发布时间】:2018-12-13 23:11:01
【问题描述】:

我正在尝试按委托连接表进行分组。我有一个任务表,每个任务都有一个 project_id。以下代码在我的控制器中运行良好,我可以按项目分组:

@task = Task.joins(:project).joins(:urgency).where(urgencies: {urgency_value: 7}).group_by(&:project_id)

这将返回一个哈希值,其中键是我加入的内容,然后索引包含该组中的每个任务。然后我可以遍历每个任务以检索其属性。

但是,每个项目都属于一个工作区(通过 workspace_id)。我想要的是有相同的查询,但按工作区分组。我的最终目标是创建一个表格,在其中一列中显示工作区名称,在第二列中显示该工作区的任务数。

我尝试了很多组合,搜索了很多论坛,但几个小时后仍然无法破解。

【问题讨论】:

  • 从您的问题中不清楚您提到的四个表(任务、项目、紧急情况、工作空间)之间的关系是什么。我认为一个任务属于一个项目,但除此之外我不得不猜测。请澄清什么属于_属于什么,什么有_很多。
  • 对不起,关系是:Task belongs_to Project 和 Urgency,Project belongs_to Workspace。

标签: ruby-on-rails join group-by


【解决方案1】:

如果您的唯一目标是获取每个工作区的任务计数,我认为您需要不同的查询。

@workspaces_with_task_counts = 
  Workspace
    .joins(:projects)
    .joins(:tasks)
    .select('workspaces.name, count(tasks.id) as task_count')
    .group(:workspace_id)

然后你可以像这样访问计数:

@workspaces_with_task_counts.each do |workspace|
  puts "#{workspace.name}: #{workspace.task_count}"
end

编辑 1

我想这就是你想要的:

Workspace
  .joins(projects: { tasks: :urgencies })
  .where(urgencies: {urgency_value: 7})
  .group(:name)
  .count

这会产生一个包含所有工作空间的哈希,其中至少有一个任务,按名称,urgency_value 为 7,以及该工作空间中的任务数:

{"workspace1"=>4, "workspace2"=>1}

编辑 2

SQL 不能在单个查询中同时返回详细信息和摘要信息。但是,我们可以得到所有的数据,然后用 Ruby 的group_by 方法将其汇总到内存中:

Task
  .joins(project: :workspace)
  .includes(project: :workspace)
  .group_by { |task| task.project.workspace.name }

这会产生以下数据结构:

{
  "workspace1": [task, task, task],
  "workspace2": [task, task],
  "workspace3": [task, task, task, task]
}

但是,这样做是有代价的。在内存中分组是一个昂贵的过程。运行该查询 10,000 次大约需要 15 秒。

事实证明,执行两个 SQL 查询实际上快了两个数量级,大约为 0.2 秒。以下是查询:

tasks = Task.joins(project: :workspace).includes(project: :workspace)
counts = tasks.group('workspaces.name').count

第一个查询获取所有任务并预加载它们关联的项目和工作区数据。第二个查询使用 ActiveRecord 的group 子句构造 SQL 语句来汇总数据。它返回这个数据结构:

{ "workspace1": 3, "workspace2": 2, "workspace3": 4 }

数据库在集合操作方面非常高效。在数据库中完成这项工作几乎总是比在 Ruby 中快得多。

【讨论】:

  • 我还想显示每个单独工作区中的所有任务。
  • @DRadnor - 更新答案。忽略 EDIT 上方的位。
  • 这很好,但是如何访问每个工作区中任务的所有属性?我需要能够从高层次上了解每个工作区中有多少高度紧迫的任务,然后看看这些任务是什么。非常感谢。
  • @DRadnor - 再次更新。希望能满足您的需求。
  • 所以看起来我需要使用效率较低的 Ruby 的 group_by 方法,因为我需要显示每个工作区的所有任务。或者我可以使用 2 个 SQL 查询,然后在 View 循环中遍历返回所有任务的查询的结果。这会同样低效吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-15
  • 1970-01-01
  • 1970-01-01
  • 2020-05-28
  • 2018-05-15
  • 1970-01-01
相关资源
最近更新 更多