Grouping and subtotals
Group rows and add subtotals when readers need to see both the individual rows and a rolled-up total per category, like revenue by region and segment.
| Rep | Revenue |
|---|---|
| EMEA | |
| Plan A | |
| Rep 1 | $612,000 |
| Plan B | |
| Rep 5 | $421,500 |
| Subtotal EMEA | $1,033,500 |
| APAC | |
| Plan A | |
| Rep 2 | $398,000 |
| Subtotal APAC | $398,000 |
| Total | $1,431,500 |
What you can do
grouping.groupByis a non-empty array of field names; a 2-field array nests groups two levels deep, outer field first.aggregationscomputes one summary value per group, each an object offieldplusagg:sum,avg,min,max, orcount.subtotalsdefaults totrueand adds a summary row after each group;grandTotaldefaults tofalseand adds one final row across the whole table.defaultExpandeddefaults totrue; set it tofalseto load every group collapsed behind its caret.totalLabel(default"Total") labels the grand total row;subtotalLabelTemplate(default"{value}") labels each subtotal row and can template{value}alongside literal text.groupingandpivotboth live onTableSpec; if a spec sets both,pivotwins, since the schema has nooneOfbetween them.
Set on TableSpec.grouping on a table panel; a chart:* panel has no grouping equivalent, since it groups by re-querying instead.
Spec
View spec
{
"id": "revenue-by-region-segment",
"type": "table",
"title": "Revenue by region and segment",
"data": {
"rows": [
{
"region": "West",
"segment": "Enterprise",
"revenue": 410000,
"deals": 12
},
{
"region": "West",
"segment": "SMB",
"revenue": 180000,
"deals": 30
},
{
"region": "East",
"segment": "Enterprise",
"revenue": 390000,
"deals": 9
},
{
"region": "East",
"segment": "SMB",
"revenue": 150000,
"deals": 22
}
]
},
"spec": {
"columns": [
{
"field": "region",
"label": "Region"
},
{
"field": "segment",
"label": "Segment"
},
{
"field": "revenue",
"format": {
"type": "currency",
"currency": "USD",
"compact": true
},
"align": "right"
},
{
"field": "deals",
"align": "right"
}
],
"grouping": {
"groupBy": [
"region",
"segment"
],
"aggregations": [
{
"field": "revenue",
"agg": "sum"
},
{
"field": "deals",
"agg": "avg"
}
],
"subtotals": true,
"grandTotal": true,
"defaultExpanded": true,
"totalLabel": "All regions",
"subtotalLabelTemplate": "Subtotal: {value}"
}
}
}groupBy nests region then segment; aggregations sums revenue and averages deals per group, and subtotalLabelTemplate templates {value} into each subtotal row’s label.
Try it live
Open the rich-tables template in the Builder
Open the rich-tables template, page p3-structure, panel p3-grouped for two-level grouping with subtotals, a grand total, two columnGroups, and three footnotes.
Build it in dvt
Every table capability on this site is a few lines of the same declarative JSON spec. Read the full spec format, or connect an AI agent to your warehouse and build one live in the quickstart.
Follow the build
dvt is in founding research. Leave your email and we'll reach out when there's something to see — no newsletters, no noise.