Feature #7655
openAbility to "Group results by" on a list of issues by the "Assignee's group"
Description
I am looking to create a report of issues based on what a group has accomplished, closed, this week.
I can create individual reports for each group by using a filter, but I had the idea of create one big report grouped by the "Assignee's group"
Files
Updated by Ryoh HAMADA 19 days ago
I commented here years ago with a simple +1, but I'd now like to add a concrete use case to better articulate why this feature matters.
Consider a manager who oversees multiple teams (groups). Their typical workflow is:
1. Filter issues with a condition such as "Assignee's group is one of [Group A, Group B, Group C]", combined with status or date conditions, to narrow down the relevant issues.
2. Group the results by "Assignee's group" to get a per-team breakdown in a single view. This lets them review each team's workload, progress, and blockers at a glance and give targeted instructions to each group.
Currently, step 1 is possible with the "Assignee's group" filter, but step 2 is not, because "Assignee's group" is not available as a "Group results by" option. Users are forced to either run a separate query for each group (losing the cross-team overview) or rely on workarounds that don't scale.
The filter and the grouping option are based on the same concept. Having one without the other creates an asymmetry that feels incomplete, especially given how naturally the two are combined in real-world management workflows. ---
Updated by Ryoh HAMADA 19 days ago
- File 0001-Add-group-by-assignees-group-for-issue-queries.patch 0001-Add-group-by-assignees-group-for-issue-queries.patch added
I'd like to share a draft patch for this feature. Please read the disclosure at the bottom before reviewing.
What the patch does¶
Adds "Assignee's group" as a "Group by" option in the issue list, alongside the existing columns (Status, Assignee, Priority, etc.).
The intended workflow this enables:
- Filter issues using the existing "Assignee's group" filter (member_of_group) to narrow the scope to specific teams.
- Group the results by "Assignee's group" to get a per-team breakdown in a single view — without running a separate query for each group.
Implementation overview¶
Three files are changed:
app/models/issue_query.rb — A new QueryAssignedToGroupColumn class is added. Its group_by_statement returns a correlated SQL subquery:
COALESCE( (SELECT MIN(gu.group_id) FROM groups_users gu WHERE gu.user_id = issues.assigned_to_id), (SELECT g.id FROM users g WHERE g.id = issues.assigned_to_id AND g.type = 'Group') )
The first branch handles the common case (issue assigned to a User: returns the user's group with the lowest id). The second branch handles issues assigned directly to a Group.
app/models/query.rb — Two lines added to grouped_query to allow column classes to convert raw integer keys returned by SQL into ActiveRecord objects. This mirrors the existing handling for QueryCustomFieldColumn.
test/unit/query_test.rb — 13 unit tests covering: column presence in groupable_columns, SQL expression structure, key types in result_count_by_group, per-group counts, group_value for each scenario (user/group/unassigned/no-group), issue ordering, total_by_group_for, and cast_group_keys edge cases.
Known limitation¶
When a user belongs to multiple groups, the issue is counted under the group with the lowest id (MIN(group_id)). There is no standard way to make a single issue appear under multiple groups within the current GROUP BY architecture. This matches the behavior of similar features in the codebase and should be documented if the patch is accepted.
What I am asking for¶
I am not submitting this as a merge-ready patch. I am sharing it as a concrete starting point for discussion. Specifically, I would welcome feedback on:
- Whether the correlated subquery approach is acceptable (vs. a JOIN-based approach for performance).
- Whether the
MIN(group_id)tie-breaking for multi-group users is an acceptable limitation, or whether a different behavior is expected. - Any issues with the test coverage or correctness.
Disclosure¶
This patch was generated with the assistance of an AI coding tool (Claude). I am not able to independently vouch for every design decision in the implementation. I have reviewed the output at a conceptual level, but I cannot claim the depth of understanding that a human author would normally have. I am disclosing this explicitly so that reviewers can apply appropriate scrutiny. If the project has a policy on AI-assisted contributions, I will follow it.
The patch is attached as 0001-Add-group-by-assignees-group-for-issue-queries.patch.
Updated by Ryoh HAMADA 2 days ago
- File assignee_group_sql_check.py assignee_group_sql_check.py added
- File 0001-Add-group-by-assignees-group-for-issue-queries-v2.patch 0001-Add-group-by-assignees-group-for-issue-queries-v2.patch added
I've reworked my draft patch for this feature. Please read the disclosure at the bottom before reviewing.
Attached files:
0001-Add-group-by-assignees-group-for-issue-queries-v2.patch: the new patch, against current master (GitHub mirror commit 785a0bb). It replaces the first draft.assignee_group_sql_check.py: a small script I used to check the SQL on several databases (see "Verification status" below).
How issues are grouped¶
"Assignee's group" is added as a "Group results by" option (and as an issue list column). Since a user can belong to several groups but each issue is listed under exactly one group heading, the group is chosen as follows:
- If the issue is assigned to a group, that group.
- Otherwise, if the "Assignee's group" filter is used with the "is" operator, the assignee's group with the lowest id among the selected groups.
- Otherwise, the assignee's group with the lowest id.
Only groups visible to the current user (Group.givable.visible, the same set offered by the "Assignee's group" filter) are considered.
Changes from the first draft¶
- Consistency with the filter: with rule 2 above, filtering on Group B never puts an issue under a Group A heading. In the first draft, a user in both A and B was always counted under the group with the lowest id, even when only B was selected in the filter.
- SQL Server compatibility: the first draft used correlated subqueries in
GROUP BYandORDER BY. SQL Server does not accept subqueries in aGROUP BYclause. This version LEFT JOINs non-correlated derived tables instead, through the existingIssueQuery#joins_for_order_statementmechanism. - Visibility: names of groups that the current user cannot see no longer appear as group headings.
- Ordering: groups are sorted by name instead of id.
- Column value: when shown as a list column, the value lists all the visible groups of the assignee, rather than only the group used for grouping.
- Performance: the first draft ran one query per issue to find its group. This version preloads assignees and caches group memberships per user within a query.
- The column is removed when the assignee field is disabled in all trackers, like the "Assignee" column.
- Test setup: the tests in the first draft created issues with
Issue.generate!(:assigned_to => ...)using newly generated users and groups who are not members of the project. Issue validation rejects such assignees, so those tests would most likely have failed in setup. I believe they were never actually run. The new tests set the assignee withupdate_columnafter creating the issue. The useful checks from the first draft (grouped?and the edge cases ofcast_group_keys) were kept.
The column name (assigned_to_group) and the small hook added to Query#grouped_query (cast_group_keys) are the same as in the first draft.
Remaining limitation¶
An issue still appears under exactly one group. For example, a user in groups A and B is shown under only one of them, even when both groups are selected in the filter. Listing an issue under several groups would require changes to the grouping architecture itself (pagination, counts and totals assume one group per issue), similar to why multi-value custom fields are not groupable.
Questions for reviewers¶
- Is the grouping rule above (preferring the groups selected in the filter) acceptable?
- Is showing all groups in the list column, while grouping under one group, acceptable, or should the column show only the group used for grouping?
- Is the join-based approach acceptable from a performance point of view?
Verification status¶
What has been checked:
- Ruby syntax of the changed files.
- That the patch applies cleanly to current master.
- That SQL of the same shape as the patch generates returns the same groups, counts, totals and ordering on SQLite 3.45, PostgreSQL 16 and MariaDB 10.11 (apart from where NULLs sort), with test data covering users in several groups, the filter, invisible groups, issues assigned directly to a group, and unassigned issues. The SQL in the attached script is written by hand to mirror the patch; it is not extracted from Redmine.
What has not been checked:
- The unit tests in the patch have not been run. I don't have a Redmine development environment.
- SQL Server.
- Behavior in the browser (issue list, CSV and PDF export).
Disclosure¶
This revision, like the first draft, was written with the assistance of an AI coding tool (Claude), including the review of the first draft. I am not able to independently vouch for every design decision in the implementation. Please apply appropriate scrutiny, and given the verification status above, please expect that the tests may need fixes. If the project has a policy on AI-assisted contributions, I will follow it.