Aggregate SOQL uses GROUP BY to compute per-group results — sums, counts, averages — and returns AggregateResult objects instead of sObjects.
apex List<AggregateResult> results = [ SELECT StageName, SUM(Amount) totalAmount, COUNT(Id) cnt FROM Opportunity GROUP BY StageName ]; for (AggregateResult ar : results) { System.debug(ar.get('StageName') + ': ' + ar.get('totalAmount')); }
Aggregates run on the server; you get one row per group. Vastly fewer rows.
Key features: SUM(), COUNT(), COUNT_DISTINCT(), AVG(), MIN(), MAX(). GROUP BY on any field. HAVING for post-aggregation filtering. GROUP BY ROLLUP / CUBE for multi-level aggregation.
Limits: 2000 rows from aggregate queries. Aliases needed for aggregate functions.
When to use: reporting/dashboards, performance (fewer rows), avoiding row limits on large queries.
A common pattern: replace a "sum by category" Apex loop with GROUP BY to dodge governor limits.
