Rails: таблица объединения по группам - PullRequest
0 голосов
/ 14 декабря 2018

Я пытаюсь сгруппировать по таблице присоединения делегатов.У меня есть таблица задач, и каждая задача имеет идентификатор проекта.Следующий код хорошо работает в моем контроллере для группирования по проекту:

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

Возвращает хеш, где ключ - это то, к чему я присоединился, а затем индекс содержит все задачи в этой группе.Затем я могу просмотреть каждую задачу, чтобы получить ее атрибуты.

Однако каждый проект принадлежит рабочей области (с помощью идентификатора рабочей области).Я хочу иметь такой же запрос, но сгруппировать по рабочему пространству.Конечная цель для меня - создать таблицу, которая отображает имя рабочего пространства в одном столбце и количество задач для этого рабочего пространства во втором столбце.

Я пробовал много комбинаций и искал много форумов, но через несколько часов все еще не смог его взломать.

1 Ответ

0 голосов
/ 14 декабря 2018

Если ваша единственная цель состоит в том, чтобы получить количество заданий для каждой рабочей области, я думаю, что вам нужен другой запрос.

@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 не способен возвращать как подробную, так и сводную информацию водин запрос.Но мы можем получить все данные, а затем суммировать их в памяти с помощью метода 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]
}

Но это делаеттак по цене.Группировка в памяти - дорогой процесс.Выполнение этого запроса 10000 раз заняло ~ 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.

...