{"id":1491,"date":"2026-09-05T09:00:00","date_gmt":"2026-09-05T03:30:00","guid":{"rendered":"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/"},"modified":"2026-09-05T09:00:00","modified_gmt":"2026-09-05T03:30:00","slug":"soql-aggregate-functions-group-by","status":"publish","type":"post","link":"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/","title":{"rendered":"SOQL Aggregate Functions and GROUP BY in Apex"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">SOQL Aggregate Functions calculate totals, averages, counts and other summary values directly in the database. Instead of loading 5,000 records and adding fees in a loop, you ask Salesforce for the total, and it returns one number. GROUP BY then splits those totals by level, trainer or month.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this post, you will learn each aggregate function, read results with AggregateResult, and filter groups with HAVING. It continues from <a href=\"https:\/\/swapnilzambare.com\/blog\/soql-relationship-queries-parent-child\/\">SOQL relationship queries<\/a> and <a href=\"https:\/\/swapnilzambare.com\/blog\/soql-basics-first-query-apex\/\">SOQL Basics<\/a>. If you have built <a href=\"https:\/\/swapnilzambare.com\/blog\/salesforce-summary-formulas-historical-trending\/\">summary formulas in reports<\/a>, you will see the same ideas, now in code.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What are SOQL Aggregate Functions?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">SOQL Aggregate Functions are functions that summarise many rows into one value. The main ones are COUNT, COUNT_DISTINCT, SUM, AVG, MIN and MAX. When you add GROUP BY, you get one summary row per group instead of one for the whole object.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Think of a class teacher with a marks register. Instead of reading every mark aloud, she reports the class average, the highest mark and the number of students who passed. Aggregate functions give your code those same summary numbers.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why SOQL Aggregate Functions Matter<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Summaries are needed everywhere, from dashboards to validation logic. Here is why SOQL Aggregate Functions matter at Bright Path Tutors.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>First, the finance page needs total course fees by level.<\/li>\n\n<li>Also, the trainer page shows how many students each course has.<\/li>\n\n<li>Next, a class must block new enrolments when a course reaches 30 students.<\/li>\n\n<li>Leaders want the average fee of online and offline courses.<\/li>\n\n<li>Finally, adding values in Apex loops wastes CPU time and heap.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">So aggregates are faster, shorter and lighter than looping over records.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How SOQL Aggregate Functions Work<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">SOQL Aggregate Functions follow a clear order. First, the WHERE clause filters records. Next, GROUP BY splits the remaining records into groups. Then each aggregate function calculates a value per group. After that, HAVING filters the groups. Finally, Apex receives a list of AggregateResult rows.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"640\" src=\"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-diagram-1-1024x640.png\" alt=\"SOQL Aggregate Functions diagram showing WHERE, GROUP BY, aggregate, HAVING and AggregateResult steps\" class=\"wp-image-1489\" srcset=\"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-diagram-1-1024x640.png 1024w, https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-diagram-1-300x188.png 300w, https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-diagram-1-768x480.png 768w, https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-diagram-1-1536x960.png 1536w, https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-diagram-1-2048x1280.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">How an aggregate query turns records into group totals.<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">COUNT and COUNT_DISTINCT<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>COUNT()<\/code> returns the number of rows as an Integer. In contrast, <code>COUNT(field)<\/code> counts rows where the field is not blank. Finally, <code>COUNT_DISTINCT(field)<\/code> counts unique values.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">SUM and AVG<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">For money, <code>SUM(Fee__c)<\/code> adds values, and <code>AVG(Fee__c)<\/code> returns the average. They work on number, currency and percent fields.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">MIN and MAX<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><code>MIN<\/code> and <code>MAX<\/code> return the smallest and largest values. They also work on dates, such as the earliest start date.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">GROUP BY and HAVING<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">GROUP BY creates one row per value, such as per level. HAVING filters those groups, much like WHERE filters records.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">AggregateResult<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Grouped results come back as <code>AggregateResult<\/code> rows. You read values with <code>get('alias')<\/code>, then cast them, because <code>get<\/code> returns a generic Object.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">SOQL Aggregate Functions at a Glance<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The table below lists each function and what it returns.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Function<\/th><th>Example<\/th><th>Returns<\/th><\/tr><\/thead><tbody><tr><td>COUNT()<\/td><td>SELECT COUNT() FROM Course__c<\/td><td>Integer count of rows<\/td><\/tr><tr><td>COUNT(field)<\/td><td>COUNT(Fee__c)<\/td><td>Rows where field is filled<\/td><\/tr><tr><td>COUNT_DISTINCT(field)<\/td><td>COUNT_DISTINCT(Level__c)<\/td><td>Number of unique values<\/td><\/tr><tr><td>SUM(field)<\/td><td>SUM(Fee__c) totalFee<\/td><td>Total of the values<\/td><\/tr><tr><td>AVG(field)<\/td><td>AVG(Fee__c) avgFee<\/td><td>Average value<\/td><\/tr><tr><td>MIN and MAX<\/td><td>MIN(Start_Date__c)<\/td><td>Smallest or largest value<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">WHERE vs HAVING<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The table below compares the two filters in aggregate queries.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Feature<\/th><th>WHERE<\/th><th>HAVING<\/th><\/tr><\/thead><tbody><tr><td>Filters<\/td><td>Individual records<\/td><td>Groups<\/td><\/tr><tr><td>Runs<\/td><td>Before grouping<\/td><td>After grouping<\/td><\/tr><tr><td>Can use aggregate functions<\/td><td>No<\/td><td>Yes<\/td><\/tr><tr><td>Example<\/td><td>WHERE Is_Online__c = true<\/td><td>HAVING COUNT(Id) &gt; 10<\/td><\/tr><tr><td>Needs GROUP BY<\/td><td>No<\/td><td>Yes<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">When to use which is simple. Use WHERE to drop records before grouping. Use HAVING to drop groups after the totals are calculated.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"640\" src=\"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-diagram-2-1024x640.png\" alt=\"SOQL Aggregate Functions diagram comparing WHERE and HAVING\" class=\"wp-image-1490\" srcset=\"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-diagram-2-1024x640.png 1024w, https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-diagram-2-300x188.png 300w, https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-diagram-2-768x480.png 768w, https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-diagram-2-1536x960.png 1536w, https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-diagram-2-2048x1280.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption class=\"wp-element-caption\">WHERE vs HAVING.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">A Real SOQL Aggregate Functions Example in Apex<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s build a small reporting service for Bright Path Tutors.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Count All Courses<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>Integer totalCourses = [SELECT COUNT() FROM Course__c];\nSystem.debug('Total courses: ' + totalCourses);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><code>COUNT()<\/code> with no field returns a plain Integer. So you assign it straight to a number, with no list involved.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Total and Average Fee by Level<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>List&lt;AggregateResult&gt; rows = [\n    SELECT Level__c level, COUNT(Id) courses,\n           SUM(Fee__c) totalFee, AVG(Fee__c) avgFee\n    FROM Course__c\n    WHERE Is_Online__c = true\n    GROUP BY Level__c\n    ORDER BY SUM(Fee__c) DESC\n];\n\nfor (AggregateResult ar : rows) {\n    String level = (String) ar.get('level');\n    Integer courses = (Integer) ar.get('courses');\n    Decimal total = (Decimal) ar.get('totalFee');\n    Decimal avg = (Decimal) ar.get('avgFee');\n    System.debug(level + ': ' + courses + ' courses, total ' + total + ', average ' + avg.setScale(0));\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Each function has an alias, such as <code>totalFee<\/code>, which makes <code>get<\/code> easy to read. GROUP BY returns one row per level, and ORDER BY sorts levels by total fee. Inside the loop, we cast each value to the right type.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Read the Output<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Here is an example of the debug log for Step 2.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>USER_DEBUG [13]|DEBUG|Intermediate: 6 courses, total 34800, average 5800\nUSER_DEBUG [13]|DEBUG|Beginner: 8 courses, total 33600, average 4200\nUSER_DEBUG [13]|DEBUG|Advanced: 3 courses, total 24000, average 8000<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Find Full Courses with HAVING<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>List&lt;AggregateResult&gt; fullCourses = [\n    SELECT Course__c courseId, COUNT(Id) students\n    FROM Enrolment__c\n    WHERE Status__c = 'Active'\n    GROUP BY Course__c\n    HAVING COUNT(Id) &gt;= 30\n];\nSystem.debug('Full courses: ' + fullCourses.size());<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">WHERE keeps only active enrolments. GROUP BY counts students per course, and HAVING keeps only courses with 30 or more. A trigger could use this result to block new enrolments.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 5: Group by Month<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>for (AggregateResult ar : [\n        SELECT CALENDAR_MONTH(Start_Date__c) month, COUNT(Id) courses\n        FROM Course__c\n        WHERE Start_Date__c = THIS_YEAR\n        GROUP BY CALENDAR_MONTH(Start_Date__c)\n    ]) {\n    System.debug('Month ' + ar.get('month') + ': ' + ar.get('courses'));\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Date functions such as CALENDAR_MONTH group records by month. This is ideal for simple charts in a Lightning component.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">SOQL Aggregate Functions and Limits<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">SOQL Aggregate Functions run as one SOQL query. However, most aggregate functions count every record they process toward the 50,000 row limit, even though only a few rows come back. So filter with WHERE before you group, especially on large objects.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Common Mistakes with SOQL Aggregate Functions<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Mixing COUNT() with other fields, which is not allowed.<\/li>\n\n<li>Selecting a field that is not in GROUP BY or inside a function.<\/li>\n\n<li>Forgetting aliases, so values come back as expr0 and expr1.<\/li>\n\n<li>Casting a SUM result to Integer instead of Decimal.<\/li>\n\n<li>Using WHERE with an aggregate function instead of HAVING.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Best Practices for SOQL Aggregate Functions<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Give every aggregate an alias that describes the value.<\/li>\n\n<li>Filter with WHERE first, then group.<\/li>\n\n<li>Use HAVING only for conditions on totals.<\/li>\n\n<li>Cast results carefully: Decimal for SUM and AVG, Integer for COUNT.<\/li>\n\n<li>Prefer aggregates over Apex loops that add values.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Practice Task<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Write a query that shows the number of active enrolments per student, but only for students in more than two courses. Hint: group Enrolment__c by Student__c and use HAVING COUNT(Id) &gt; 2.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Most Asked Interview Questions on SOQL Aggregate Functions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">SOQL Aggregate Functions are a favourite interview topic, because they test both SOQL and Apex skills. Here are the 20 questions asked most.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Basic Questions on SOQL Aggregate Functions<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q1: What are aggregate functions in SOQL?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">They summarise many rows into one value. The main ones are COUNT, COUNT_DISTINCT, SUM, AVG, MIN and MAX.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q2: What does COUNT() return?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It returns an Integer with the number of rows, so you assign it to a number, not a list.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q3: What is the difference between COUNT() and COUNT(field)?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">COUNT() counts all rows. In contrast, COUNT(field) counts only rows where that field is not blank.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q4: What is AggregateResult?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It is the Apex type for rows returned by grouped or aggregate queries. You read values with get().<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q5: What is an alias in an aggregate query?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It is a name after the function, such as SUM(Fee__c) totalFee. Then you read it with ar.get(&#8216;totalFee&#8217;).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q6: What happens if you do not use an alias?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Salesforce names values expr0, expr1 and so on, which makes code harder to read.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q7: What does GROUP BY do?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It creates one result row for each unique value of the grouped field, such as one row per level.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Code and Scenario Questions on SOQL Aggregate Functions<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q8: What is the difference between WHERE and HAVING?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">WHERE filters records before grouping. HAVING, however, filters groups after the totals are calculated.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q9: How do you find courses with more than 30 students?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Group enrolments by course and add HAVING COUNT(Id) &gt; 30.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q10: Which type do you cast SUM and AVG results to?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Usually Decimal, because they can return decimal values.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q11: Can you use COUNT() with other fields in the SELECT?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">No. COUNT() must be used alone. Instead, use COUNT(Id) with other fields and GROUP BY.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q12: How do you group records by month?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Use a date function, such as GROUP BY CALENDAR_MONTH(Start_Date__c).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q13: Can you ORDER BY an aggregate value?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. For example, ORDER BY SUM(Fee__c) DESC sorts groups by total.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q14: How do you count unique values?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Use COUNT_DISTINCT(field), for example COUNT_DISTINCT(Level__c).<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Advanced Questions on SOQL Aggregate Functions<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q15: Do aggregate queries help with governor limits?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">They use one query, and they save CPU and heap. However, most functions still count processed records toward the 50,000 row limit.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q16: What is GROUP BY ROLLUP?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It adds subtotal rows for each group level and a grand total, similar to report subtotals.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q17: Can you use aggregate functions in a SOQL for loop?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. A for loop over an aggregate query is a clean way to process grouped rows.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q18: Why might an aggregate query be slow on large objects?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It may scan many records. So add selective WHERE filters on indexed fields before grouping.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q19: Can you group by a relationship field?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Yes. For example, you can group enrolments by Course__c, then read course names in another query or with a relationship field in the group.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Q20: When would you use Apex loops instead of aggregates?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Only when the calculation is too complex for SOQL, such as custom business rules per record. Otherwise, aggregates are faster and simpler.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Official Resources<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/developer.salesforce.com\/docs\/atlas.en-us.soql_sosl.meta\/soql_sosl\/sforce_api_calls_soql_select_agg_functions.htm\" target=\"_blank\" rel=\"noopener noreferrer\">Aggregate Functions (Salesforce Developers)<\/a><\/li>\n\n<li><a href=\"https:\/\/developer.salesforce.com\/docs\/atlas.en-us.apexcode.meta\/apexcode\/langCon_apex_SOQL_agg_fns.htm\" target=\"_blank\" rel=\"noopener noreferrer\">Working with SOQL Aggregate Functions (Apex Developer Guide)<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Quick Recap<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>SOQL Aggregate Functions summarise records into counts, totals, averages and ranges.<\/li>\n\n<li>GROUP BY gives one summary row per value.<\/li>\n\n<li>HAVING filters groups, while WHERE filters records.<\/li>\n\n<li>Read results with AggregateResult, aliases and careful casting.<\/li>\n\n<li>Filter before grouping to stay within row limits.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">What&#8217;s Next?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Many filters use dates and Apex values. Next, read our guide to <a href=\"https:\/\/swapnilzambare.com\/blog\/soql-date-literals-bind-variables\/\">SOQL date literals and bind variables<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>SOQL Aggregate Functions calculate totals, averages, counts and other summary values directly in the database. Instead of loading 5,000 records and adding fees in&hellip;<\/p>\n","protected":false},"author":1,"featured_media":1488,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_swapz_level":"","_swapz_series_part":0,"_swapz_hide_toc":false,"_swapz_hide_featured":false,"_swapz_description":"","footnotes":""},"categories":[8,96],"tags":[98,26,91,7,97,105],"swapz_series":[],"class_list":["post-1491","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-salesforce","category-salesforce-developer","tag-apex","tag-intermediate","tag-interview-questions","tag-salesforce","tag-salesforce-developer","tag-soql"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>SOQL Aggregate Functions and GROUP BY in Apex<\/title>\n<meta name=\"description\" content=\"SOQL Aggregate Functions explained simply: COUNT, SUM, AVG, MIN, MAX, GROUP BY, HAVING, AggregateResult in Apex and 20 interview questions.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"SOQL Aggregate Functions and GROUP BY in Apex\" \/>\n<meta property=\"og:description\" content=\"SOQL Aggregate Functions explained simply: COUNT, SUM, AVG, MIN, MAX, GROUP BY, HAVING, AggregateResult in Apex and 20 interview questions.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/\" \/>\n<meta property=\"og:site_name\" content=\"Swapnil Zambare - Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-05T03:30:00+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-featured.png\" \/>\n\t<meta property=\"og:image:width\" content=\"2400\" \/>\n\t<meta property=\"og:image:height\" content=\"1260\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Swapnil Zambare\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Swapnil Zambare\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/soql-aggregate-functions-group-by\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/soql-aggregate-functions-group-by\\\/\"},\"author\":{\"name\":\"Swapnil Zambare\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#\\\/schema\\\/person\\\/922ac0131aaa7088c78c2cb1700e0c9a\"},\"headline\":\"SOQL Aggregate Functions and GROUP BY in Apex\",\"datePublished\":\"2026-09-05T03:30:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/soql-aggregate-functions-group-by\\\/\"},\"wordCount\":1563,\"publisher\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/soql-aggregate-functions-group-by\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/soql-aggregate-functions-group-by-featured.png\",\"keywords\":[\"Apex\",\"Intermediate\",\"Interview Questions\",\"Salesforce\",\"Salesforce Developer\",\"SOQL\"],\"articleSection\":[\"Salesforce\",\"Salesforce Developer\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/soql-aggregate-functions-group-by\\\/\",\"url\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/soql-aggregate-functions-group-by\\\/\",\"name\":\"SOQL Aggregate Functions and GROUP BY in Apex\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/soql-aggregate-functions-group-by\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/soql-aggregate-functions-group-by\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/soql-aggregate-functions-group-by-featured.png\",\"datePublished\":\"2026-09-05T03:30:00+00:00\",\"description\":\"SOQL Aggregate Functions explained simply: COUNT, SUM, AVG, MIN, MAX, GROUP BY, HAVING, AggregateResult in Apex and 20 interview questions.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/soql-aggregate-functions-group-by\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/soql-aggregate-functions-group-by\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/soql-aggregate-functions-group-by\\\/#primaryimage\",\"url\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/soql-aggregate-functions-group-by-featured.png\",\"contentUrl\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/11\\\/soql-aggregate-functions-group-by-featured.png\",\"width\":2400,\"height\":1260,\"caption\":\"SOQL Aggregate Functions featured image: title card with an Apex code example\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/soql-aggregate-functions-group-by\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"SOQL Aggregate Functions and GROUP BY in Apex\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/\",\"name\":\"Swapnil Zambare - Blog\",\"description\":\"Salesforce &amp; Tech Guides\",\"publisher\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#organization\",\"name\":\"Swapnil Zambare - Blog\",\"url\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/site-icon-512.png\",\"contentUrl\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/09\\\/site-icon-512.png\",\"width\":512,\"height\":512,\"caption\":\"Swapnil Zambare - Blog\"},\"image\":{\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.linkedin.com\\\/in\\\/theSwapnilZambare\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/#\\\/schema\\\/person\\\/922ac0131aaa7088c78c2cb1700e0c9a\",\"name\":\"Swapnil Zambare\",\"sameAs\":[\"https:\\\/\\\/swapnilzambare.com\\\/blog\"],\"url\":\"https:\\\/\\\/swapnilzambare.com\\\/blog\\\/author\\\/swapnil-zambare\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"SOQL Aggregate Functions and GROUP BY in Apex","description":"SOQL Aggregate Functions explained simply: COUNT, SUM, AVG, MIN, MAX, GROUP BY, HAVING, AggregateResult in Apex and 20 interview questions.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/","og_locale":"en_US","og_type":"article","og_title":"SOQL Aggregate Functions and GROUP BY in Apex","og_description":"SOQL Aggregate Functions explained simply: COUNT, SUM, AVG, MIN, MAX, GROUP BY, HAVING, AggregateResult in Apex and 20 interview questions.","og_url":"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/","og_site_name":"Swapnil Zambare - Blog","article_published_time":"2026-09-05T03:30:00+00:00","og_image":[{"width":2400,"height":1260,"url":"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-featured.png","type":"image\/png"}],"author":"Swapnil Zambare","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Swapnil Zambare","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/#article","isPartOf":{"@id":"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/"},"author":{"name":"Swapnil Zambare","@id":"https:\/\/swapnilzambare.com\/blog\/#\/schema\/person\/922ac0131aaa7088c78c2cb1700e0c9a"},"headline":"SOQL Aggregate Functions and GROUP BY in Apex","datePublished":"2026-09-05T03:30:00+00:00","mainEntityOfPage":{"@id":"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/"},"wordCount":1563,"publisher":{"@id":"https:\/\/swapnilzambare.com\/blog\/#organization"},"image":{"@id":"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/#primaryimage"},"thumbnailUrl":"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-featured.png","keywords":["Apex","Intermediate","Interview Questions","Salesforce","Salesforce Developer","SOQL"],"articleSection":["Salesforce","Salesforce Developer"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/","url":"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/","name":"SOQL Aggregate Functions and GROUP BY in Apex","isPartOf":{"@id":"https:\/\/swapnilzambare.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/#primaryimage"},"image":{"@id":"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/#primaryimage"},"thumbnailUrl":"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-featured.png","datePublished":"2026-09-05T03:30:00+00:00","description":"SOQL Aggregate Functions explained simply: COUNT, SUM, AVG, MIN, MAX, GROUP BY, HAVING, AggregateResult in Apex and 20 interview questions.","breadcrumb":{"@id":"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/#primaryimage","url":"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-featured.png","contentUrl":"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/11\/soql-aggregate-functions-group-by-featured.png","width":2400,"height":1260,"caption":"SOQL Aggregate Functions featured image: title card with an Apex code example"},{"@type":"BreadcrumbList","@id":"https:\/\/swapnilzambare.com\/blog\/soql-aggregate-functions-group-by\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/swapnilzambare.com\/blog\/"},{"@type":"ListItem","position":2,"name":"SOQL Aggregate Functions and GROUP BY in Apex"}]},{"@type":"WebSite","@id":"https:\/\/swapnilzambare.com\/blog\/#website","url":"https:\/\/swapnilzambare.com\/blog\/","name":"Swapnil Zambare - Blog","description":"Salesforce &amp; Tech Guides","publisher":{"@id":"https:\/\/swapnilzambare.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/swapnilzambare.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/swapnilzambare.com\/blog\/#organization","name":"Swapnil Zambare - Blog","url":"https:\/\/swapnilzambare.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/swapnilzambare.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/09\/site-icon-512.png","contentUrl":"https:\/\/swapnilzambare.com\/blog\/wp-content\/uploads\/2026\/09\/site-icon-512.png","width":512,"height":512,"caption":"Swapnil Zambare - Blog"},"image":{"@id":"https:\/\/swapnilzambare.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.linkedin.com\/in\/theSwapnilZambare"]},{"@type":"Person","@id":"https:\/\/swapnilzambare.com\/blog\/#\/schema\/person\/922ac0131aaa7088c78c2cb1700e0c9a","name":"Swapnil Zambare","sameAs":["https:\/\/swapnilzambare.com\/blog"],"url":"https:\/\/swapnilzambare.com\/blog\/author\/swapnil-zambare\/"}]}},"_links":{"self":[{"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/posts\/1491","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/comments?post=1491"}],"version-history":[{"count":0,"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/posts\/1491\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/media\/1488"}],"wp:attachment":[{"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/media?parent=1491"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/categories?post=1491"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/tags?post=1491"},{"taxonomy":"swapz_series","embeddable":true,"href":"https:\/\/swapnilzambare.com\/blog\/wp-json\/wp\/v2\/swapz_series?post=1491"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}