afv-library/skills/platform-data-manage/assets/soql/aggregate.soql

227 lines
12 KiB
Plaintext

-- ═══════════════════════════════════════════════════════════════════════════════
-- AGGREGATE QUERIES (GROUP BY Pattern)
-- ═══════════════════════════════════════════════════════════════════════════════
--
-- Aggregate functions summarize data across records.
-- Use with GROUP BY to create summary reports.
--
-- AGGREGATE FUNCTIONS:
-- • COUNT() - Count records
-- • COUNT(field) - Count non-null field values
-- • COUNT_DISTINCT(field) - Count unique values
-- • SUM(field) - Sum numeric field values
-- • AVG(field) - Average of numeric field values
-- • MIN(field) - Minimum value
-- • MAX(field) - Maximum value
--
-- IMPORTANT:
-- • Aggregate queries return AggregateResult objects, not SObjects
-- • Cannot use with Bulk API export (use sf data query instead)
-- • GROUP BY fields must appear in SELECT or be aggregated
--
-- ═══════════════════════════════════════════════════════════════════════════════
-- ───────────────────────────────────────────────────────────────────────────────
-- BASIC COUNT: Count records by Industry
-- ───────────────────────────────────────────────────────────────────────────────
SELECT Industry, COUNT(Id) RecordCount
FROM Account
WHERE Industry != null
GROUP BY Industry
ORDER BY COUNT(Id) DESC
-- ───────────────────────────────────────────────────────────────────────────────
-- SUM and AVG: Revenue by Industry
-- ───────────────────────────────────────────────────────────────────────────────
SELECT Industry,
COUNT(Id) AccountCount,
SUM(AnnualRevenue) TotalRevenue,
AVG(AnnualRevenue) AvgRevenue,
MIN(AnnualRevenue) MinRevenue,
MAX(AnnualRevenue) MaxRevenue
FROM Account
WHERE Industry != null
AND AnnualRevenue != null
GROUP BY Industry
HAVING SUM(AnnualRevenue) > 1000000
ORDER BY SUM(AnnualRevenue) DESC
-- ───────────────────────────────────────────────────────────────────────────────
-- OPPORTUNITY PIPELINE: Revenue by Stage
-- ───────────────────────────────────────────────────────────────────────────────
SELECT StageName,
COUNT(Id) OpportunityCount,
SUM(Amount) TotalAmount,
AVG(Amount) AvgDealSize,
AVG(Probability) AvgProbability
FROM Opportunity
WHERE IsClosed = false
GROUP BY StageName
ORDER BY SUM(Amount) DESC
-- ───────────────────────────────────────────────────────────────────────────────
-- COUNT_DISTINCT: Unique values
-- ───────────────────────────────────────────────────────────────────────────────
SELECT LeadSource,
COUNT(Id) TotalOpportunities,
COUNT_DISTINCT(AccountId) UniqueAccounts,
SUM(Amount) TotalPipeline
FROM Opportunity
WHERE CreatedDate = THIS_YEAR
AND LeadSource != null
GROUP BY LeadSource
ORDER BY SUM(Amount) DESC
-- ───────────────────────────────────────────────────────────────────────────────
-- MULTIPLE GROUP BY: Revenue by Industry and Type
-- ───────────────────────────────────────────────────────────────────────────────
SELECT Account.Industry, Account.Type,
COUNT(Id) OpportunityCount,
SUM(Amount) TotalAmount
FROM Opportunity
WHERE Account.Industry != null
AND Account.Type != null
GROUP BY Account.Industry, Account.Type
ORDER BY Account.Industry, SUM(Amount) DESC
-- ───────────────────────────────────────────────────────────────────────────────
-- DATE FUNCTIONS: Group by Time Period
-- ───────────────────────────────────────────────────────────────────────────────
-- By Calendar Month
SELECT CALENDAR_MONTH(CloseDate) Month,
CALENDAR_YEAR(CloseDate) Year,
COUNT(Id) ClosedDeals,
SUM(Amount) Revenue
FROM Opportunity
WHERE StageName = 'Closed Won'
AND CloseDate = THIS_YEAR
GROUP BY CALENDAR_YEAR(CloseDate), CALENDAR_MONTH(CloseDate)
ORDER BY CALENDAR_YEAR(CloseDate), CALENDAR_MONTH(CloseDate)
-- By Week
SELECT WEEK_IN_YEAR(CreatedDate) Week,
COUNT(Id) NewLeads
FROM Lead
WHERE CreatedDate = THIS_QUARTER
GROUP BY WEEK_IN_YEAR(CreatedDate)
ORDER BY WEEK_IN_YEAR(CreatedDate)
-- By Day of Week
SELECT DAY_IN_WEEK(CreatedDate) DayOfWeek,
COUNT(Id) CasesOpened
FROM Case
WHERE CreatedDate = LAST_90_DAYS
GROUP BY DAY_IN_WEEK(CreatedDate)
ORDER BY DAY_IN_WEEK(CreatedDate)
-- ───────────────────────────────────────────────────────────────────────────────
-- HAVING: Filter aggregated results
-- ───────────────────────────────────────────────────────────────────────────────
SELECT OwnerId, Owner.Name,
COUNT(Id) OpenOpportunities,
SUM(Amount) PipelineValue
FROM Opportunity
WHERE IsClosed = false
GROUP BY OwnerId, Owner.Name
HAVING COUNT(Id) >= 5
AND SUM(Amount) >= 100000
ORDER BY SUM(Amount) DESC
-- ───────────────────────────────────────────────────────────────────────────────
-- CASE METRICS: Cases by Status and Priority
-- ───────────────────────────────────────────────────────────────────────────────
SELECT Status, Priority,
COUNT(Id) CaseCount,
AVG(CreatedDate) AvgCreatedDate
FROM Case
WHERE CreatedDate = THIS_QUARTER
GROUP BY Status, Priority
ORDER BY Status, Priority
-- ───────────────────────────────────────────────────────────────────────────────
-- ACCOUNT HEALTH: Accounts with Opportunity Metrics
-- ───────────────────────────────────────────────────────────────────────────────
SELECT AccountId, Account.Name,
COUNT(Id) TotalOpportunities,
SUM(CASE WHEN StageName = 'Closed Won' THEN 1 ELSE 0 END) WonOpportunities,
SUM(Amount) TotalPipeline,
MIN(CloseDate) EarliestClose,
MAX(CloseDate) LatestClose
FROM Opportunity
WHERE AccountId != null
GROUP BY AccountId, Account.Name
HAVING COUNT(Id) >= 3
ORDER BY SUM(Amount) DESC
LIMIT 50
-- ───────────────────────────────────────────────────────────────────────────────
-- ROLLUP: Subtotals (Enterprise Edition+)
-- ───────────────────────────────────────────────────────────────────────────────
SELECT Industry, Type,
COUNT(Id) AccountCount
FROM Account
WHERE Industry != null
GROUP BY ROLLUP(Industry, Type)
-- ───────────────────────────────────────────────────────────────────────────────
-- CUBE: All dimension combinations (Enterprise Edition+)
-- ───────────────────────────────────────────────────────────────────────────────
SELECT Industry, Type,
COUNT(Id) AccountCount,
SUM(AnnualRevenue) TotalRevenue
FROM Account
WHERE Industry != null AND Type != null
GROUP BY CUBE(Industry, Type)
-- ═══════════════════════════════════════════════════════════════════════════════
-- APEX PROCESSING PATTERN
-- ═══════════════════════════════════════════════════════════════════════════════
/*
// Aggregate queries return List<AggregateResult>
List<AggregateResult> results = [
SELECT Industry,
COUNT(Id) RecordCount,
SUM(AnnualRevenue) TotalRevenue
FROM Account
WHERE Industry != null
GROUP BY Industry
ORDER BY SUM(AnnualRevenue) DESC
];
// Process aggregate results
for (AggregateResult ar : results) {
String industry = (String) ar.get('Industry');
Integer count = (Integer) ar.get('RecordCount');
Decimal revenue = (Decimal) ar.get('TotalRevenue');
System.debug(industry + ': ' + count + ' accounts, $' + revenue);
}
// Using alias for complex expressions
List<AggregateResult> oppResults = [
SELECT StageName Stage,
COUNT(Id) cnt,
SUM(Amount) total
FROM Opportunity
GROUP BY StageName
];
for (AggregateResult ar : oppResults) {
String stage = (String) ar.get('Stage');
Integer count = (Integer) ar.get('cnt');
Decimal total = (Decimal) ar.get('total');
System.debug(stage + ': ' + count + ' opps worth $' + total);
}
*/
-- ═══════════════════════════════════════════════════════════════════════════════
-- SF CLI USAGE
-- ═══════════════════════════════════════════════════════════════════════════════
-- sf data query \
-- --query "SELECT Industry, COUNT(Id) RecordCount, SUM(AnnualRevenue) TotalRevenue FROM Account WHERE Industry != null GROUP BY Industry ORDER BY SUM(AnnualRevenue) DESC" \
-- --target-org myorg \
-- --json
--
-- NOTE: Aggregate queries do NOT work with sf data export bulk
-- Use sf data query for aggregate results