DAR*_*_ad 4 join group-by ruby-on-rails
我正在尝试按委托连接表进行分组。我有一个任务表,每个任务都有一个project_id。以下代码在我的控制器中运行良好,可供我按项目分组:
@task = Task.joins(:project).joins(:urgency).where(urgencies: {urgency_value: 7}).group_by(&:project_id)
Run Code Online (Sandbox Code Playgroud)
这会返回一个散列,其中键是我加入的内容,然后索引包含该组中的每个任务。然后我可以循环遍历每个任务以检索其属性。
然而,每个项目都属于一个工作区(通过workspace_id)。我想要的是具有相同的查询,但按工作区分组。我的最终目标是创建一个表格,其中一列显示工作区名称,第二列显示该工作区的任务数量。
我尝试了很多组合并搜索了很多论坛,但几个小时后仍然无法破解它。
如果您的唯一目标是获取每个工作区的任务计数,我认为您需要不同的查询。
@workspaces_with_task_counts =
Workspace
.joins(:projects)
.joins(:tasks)
.select('workspaces.name, count(tasks.id) as task_count')
.group(:workspace_id)
Run Code Online (Sandbox Code Playgroud)
然后你可以像这样访问计数:
@workspaces_with_task_counts.each do |workspace|
puts "#{workspace.name}: #{workspace.task_count}"
end
Run Code Online (Sandbox Code Playgroud)
编辑1
我想这就是你想要的:
Workspace
.joins(projects: { tasks: :urgencies })
.where(urgencies: {urgency_value: 7})
.group(:name)
.count
Run Code Online (Sandbox Code Playgroud)
这会生成一个散列,其中包含至少一个任务的所有工作区,其中 Urgency_value 为 7(按名称)以及该工作区中的任务数:
{"workspace1"=>4, "workspace2"=>1}
Run Code Online (Sandbox Code Playgroud)
编辑2
SQL 无法在单个查询中同时返回详细信息和摘要信息。但是,我们可以获取所有数据,然后用 Ruby 的group_by方法将其汇总在内存中:
Task
.joins(project: :workspace)
.includes(project: :workspace)
.group_by { |task| task.project.workspace.name }
Run Code Online (Sandbox Code Playgroud)
这会产生以下数据结构:
{
"workspace1": [task, task, task],
"workspace2": [task, task],
"workspace3": [task, task, task, task]
}
Run Code Online (Sandbox Code Playgroud)
但是,这样做是有代价的。在内存中进行分组是一个昂贵的过程。运行该查询 10,000 次大约需要 15 秒。
事实证明,执行两个 SQL 查询实际上快了两个数量级,大约为 0.2 秒。以下是查询:
tasks = Task.joins(project: :workspace).includes(project: :workspace)
counts = tasks.group('workspaces.name').count
Run Code Online (Sandbox Code Playgroud)
第一个查询获取所有任务并预加载其关联的项目和工作区数据。第二个查询使用 ActiveRecord 的group子句构建 SQL 语句来汇总数据。它返回这个数据结构:
{ "workspace1": 3, "workspace2": 2, "workspace3": 4 }
Run Code Online (Sandbox Code Playgroud)
数据库在集合操作方面非常高效。在数据库中完成这项工作几乎总是比在 Ruby 中快得多。
| 归档时间: |
|
| 查看次数: |
8099 次 |
| 最近记录: |