Grouping with subtotals

The group option folds the rows of any data tag into one occurrence per distinct value of a field. Each group holds that value, $count - the number of rows in the group - and rows, the group's own rows as nested data. Inside {rows} a field is the row's own value again.

PHP
HTML
fragments/grouping_1.pad
Result
{data 'orders'}
[ {"customer":"Ann","number":101,"total":40}, {"customer":"Bob","number":102,"total":15},
{"customer":"Ann","number":103,"total":25}, {"customer":"Cleo","number":104,"total":60},
{"customer":"Bob","number":105,"total":35} ]
{/data}

{orders group='customer', sum='total'}
<h4>{$customer}: {$count} orders, {$total}</h4>
{rows}
<p>Order {$number}: {$total}</p>
{/rows}
{/orders}

Ann: 2 orders, 65

Order 101: 40

Order 103: 25

Bob: 2 orders, 50

Order 102: 15

Order 105: 35

Cleo: 1 orders, 60

Order 104: 60

Aggregates

sum, avg, min and max name the fields to aggregate over each group's rows. The aggregate is stored under the field's own name - {$total} above is the sum - and under the aggregate joined to it - {$sum_total}, {$avg_total} - so one field can be summed and averaged at once. A field list such as sum='total, quantity' aggregates each of them.

PHP
HTML
fragments/grouping_2.pad
Result
{data 'orders'}
[ {"customer":"Ann","number":101,"total":40}, {"customer":"Bob","number":102,"total":15},
{"customer":"Ann","number":103,"total":25}, {"customer":"Cleo","number":104,"total":60},
{"customer":"Bob","number":105,"total":35} ]
{/data}

<table>
<tr><th>Customer</th><th>Orders</th><th>Total</th><th>Average</th><th>Smallest</th><th>Largest</th></tr>
{orders group='customer', sum='total', avg='total', min='total', max='total', sort='total DESC'}
<tr>
<td>{$customer}</td><td>{$count}</td><td>{$total}</td>
<td>{$avg_total}</td><td>{$min_total}</td><td>{$max_total}</td>
</tr>
{/orders}
</table>
Customer Orders Total Average Smallest Largest
Ann 2 65 32.5 25 40
Cleo 1 60 60 60 60
Bob 2 50 25 15 35

In order with the other options

Handling options run in the order they are written. Groups come in the order their first row appears: a sort written before the group orders the groups and the rows inside them, a sort written after it orders the groups - also on an aggregate, as above. first, page and where written after the group count groups: {orders group='customer', where='$count gt 1'} keeps the customers with more than one order. Several fields - group='year, month' - group on the combination, and {rows group='month'} groups again inside a group.