This guide walks through 38 foundational SOQL queries — filtering, ordering, and basic relationship queries. Each entry below includes the full problem statement, the governor-limit and best-practice constraints it's testing, and a numbered approach to solving it — then you can open the same problem in ApexArena's browser-based Apex editor and get instant pass/fail feedback against real test cases.
Write a SOQL query using aggregate functions to produce a summary report of
Opportunity records grouped by StageName.
For each stage, return the count, total amount, and average amount.
Stage | Count | Total | Average Prospecting | 24 | 1,200,000 | 50,000 Closed Won | 18 | 4,500,000 | 250,000
Write a method that returns all Lead records
created within the last 30 days, ordered newest-first.
public static List<Lead> getRecentLeads()
SOQL date literals let you write time-relative filters without hardcoding dates.
They are written without quotes and some accept a numeric suffix (:N):
WHERE CreatedDate >= LAST_N_DAYS:30
Common date literals:
TODAY, YESTERDAY, TOMORROWTHIS_WEEK, LAST_WEEK, NEXT_WEEKLAST_N_DAYS:n — the past n days (including today)NEXT_N_DAYS:n — the next n daysTHIS_MONTH, LAST_MONTH, NEXT_MONTHCreatedDate DESC (newest first)Id, FirstName, LastName, CreatedDateWrite a SOQL query inside getAccountsWithIndustry() that retrieves
all Account Name and Industry fields,
ordered alphabetically by Name.
Name and Industry.List all Closed Won Opportunities with their Name, Amount, and CloseDate, sorted by highest Amount first.
StageName = 'Closed Won'Name, Amount, CloseDate, AccountIdAmount DESCWrite a SOQL query that retrieves the five most recently created Leads, ordered from newest to oldest.
Id, FirstName, LastName, Email, Company, and CreatedDate.Compute and return the average Amount of all Closed Won
Opportunities as a Decimal. Return 0 if no records exist.
Amount field with an average function, aliasing the aggregate result exactly avgAmt (required for grading)avgAmt aliasReturn all Opportunities whose CloseDate falls within the next 7 calendar days, ordered soonest-first.
NEXT_N_DAYS:7 matches any date from tomorrow through 7 days
from today (inclusive). No Apex date arithmetic is needed.
CloseDate = NEXT_N_DAYS:7CloseDate ASCReturn all Opportunities whose CloseDate falls within the current calendar month, ordered from earliest to latest close date.
THIS_MONTH covers the entire current month — first day through
last day — regardless of today's date.
Aggregate the Lead object to find the total number of Leads in each Lead Source category, ordered from the most to the least common source.
LeadSource, COUNT(Id) totalLeadLeadSourceCOUNT(Id) DESCRetrieve all Accounts whose Billing Postal Code starts with the digit "9".
LIKE '9%' in SOQL matches any string beginning with "9".
The % wildcard matches zero or more characters.
BillingPostalCode LIKE '9%'Id, Name, BillingPostalCodeName ASCRetrieve Opportunities in the "Negotiation" stage that also have an Amount greater than $100,000.
StageName is Negotiation and whose Amount exceeds 100,000Id, Name, Amount, StageName, AccountIdAmount, highest firstList all open Opportunities whose CloseDate is within the next 14 days, sorted soonest-to-close first.
CloseDate <= NEXT_N_DAYS:14IsClosed = falseCloseDate ASCReturn all Opportunities created by a specific user, identified by their Salesforce User Id, ordered most-recent first.
CreatedById matches the passed-in user IdgetOpportunitiesCreatedByUser(Id userId)Id, Name, Amount, StageName, CreatedDateCreatedDate, most recent firstWrite a child-to-parent SOQL query that retrieves a list of Contacts along with the name of each Contact's parent Account.
Id, FirstName, LastName, and Email, plus their parent Account's Name.Use dot notation (Account.Name) to traverse the relationship from child (Contact) to parent (Account).
Write a child-to-parent SOQL query that retrieves open Opportunities along with the Industry of their parent Account.
Id, Name, StageName, CloseDate, and Amount, plus its parent Account's Industry.Retrieve Contacts along with their parent Account's billing address fields (City, State, Country) using child-to-parent SOQL.
Id, FirstName, LastName, and Email, plus their parent Account's City, State, and Country billing fields.Write a child-to-parent SOQL query that retrieves open Cases with their parent Account name.
Id, CaseNumber, Subject, Status, and Priority, plus its parent Account's Name.Write a parent-to-child SOQL query that retrieves Accounts together with a list of their related Contacts using a subquery.
Id, Name, Phone, and Website, along with a nested list of its related contacts' Id, FirstName, LastName, and Email.Parent-to-child uses a subquery in parentheses to pull related child records inline. Note the plural relationship name for Contacts, not the singular object name.
Retrieve Accounts with a subquery for their open Opportunities. The subquery should filter and order the child records.
Id, Name, Industry, and AnnualRevenue, plus a nested list of its still-open opportunities' Id, Name, StageName, Amount, and CloseDate.Every problem above runs in a real in-browser Apex editor with instant pass/fail feedback and best-practice linting. No Salesforce org needed.
Create Free Account →Inside SOQLPracticeService, implement getAllAccounts()
that returns every Account with its Id,
Name, and Industry fields.
Id, Name, and Industry.List<Account>Implement getAccountsByIndustry(String industryName) that returns
all Accounts whose Industry matches the given parameter.
Id, Name, and Industry.Implement getTopAccounts() that returns only the first
5 Account records with Id and Name.
Id and Name.Implement getAccountsSorted() that returns all Accounts
sorted from newest to oldest by CreatedDate.
Id, Name, and CreatedDate of every AccountAccount objectImplement getAccountsStartsWithA() that returns all Accounts
whose Name begins with the letter "A".
Id, NameName LIKE 'A%'% wildcard matches any suffixImplement getContactsWithEmail() that returns all Contacts
where the Email field is populated (not null).
Id, FirstName, LastName, and Email of matching ContactsContact objectEmail field is blankImplement getHighValueOpportunities() that returns all
Opportunities with Amount greater than 50,000.
Id, Name, and Amount of matching OpportunitiesOpportunity objectAmount is strictly greater than 50,000Implement getClosedWonOpps() that returns all Opportunities
in the "Closed Won" stage.
Id, Name, and StageName of matching OpportunitiesOpportunity objectImplement getTodayContacts() that returns all Contacts
created today using a SOQL date literal.
Id and Name of matching ContactsContact objectCreatedDate falls within the current day, expressed using a SOQL date literal rather than a hardcoded dateDate literals like TODAY, YESTERDAY,
THIS_WEEK, LAST_N_DAYS:n are evaluated at query
time in the user's timezone.
Implement getAccountCount() that returns the
total number of Account records as an Integer.
SELECT COUNT() — no field name inside COUNT()AccountIntegerImplement getAccountsWithLimitedContacts() that fetches each
Account with at most 3 of its Contacts.
Id and NameId and LastName), capped at 3 per AccountImplement getRecentLeads() that returns the
10 most recently created Leads with their Name
and Company.
Id, Name, and Company of matching LeadsLead objectImplement getThisMonthOpportunities() that returns all
Opportunities whose CloseDate falls within the
current calendar month.
Id, Name, and CloseDate of matching OpportunitiesOpportunity objectCloseDate falls in the current calendar month, expressed using a SOQL date literal rather than a hardcoded date rangeTODAY, YESTERDAYTHIS_WEEK, LAST_WEEK, NEXT_WEEKTHIS_MONTH, LAST_MONTH, NEXT_MONTHLAST_N_DAYS:n, NEXT_N_DAYS:nImplement getAccountsByIndustries() that returns Accounts
in the Banking, IT, or Healthcare industries using the
IN operator.
Id, Name, and Industry of matching AccountsAccount objectIndustry is one of Banking, IT, or Healthcare, using the IN operator against that set of valuesIN is equivalent to multiple OR conditions.
It accepts a comma-separated list of values enclosed in parentheses.
Write an Apex class ContactDomainQuery with a method
getContactsByDomain(String domain) that returns every Contact whose
Email ends with @<domain> (e.g. passing
"acme.com" should match jane@acme.com).
String variable first, then bind
that variable into the query's LIKE comparison — never concatenate
domain directly into the SOQL string.WITH SECURITY_ENFORCED and an ORDER BY / LIMIT.String variable (:pattern) instead of
splicing user input into the query text is what keeps this SOQL-injection-safe — Apex only
allows binding a simple variable reference, not an inline expression, inside
LIKE :('%@' + domain).WITH SECURITY_ENFORCED enforces field- and object-level security for the
running user.WHERE clause with a sane LIMIT.Write an Apex class AccountsByTypeQuery with a method
getAccountsByTypes(List<String> types) that returns every Account whose
Type is one of the values in the given list.
Type matches any value in the bound list parameter.Name ascending.List<String> parameter directly into an IN
clause is the standard, injection-safe way to filter against a caller-supplied set of values.LIMIT even when the input list is short.Write an Apex class WonOpportunitiesQuery with a method
getWonOpportunities() that returns every won Opportunity, ordered from
highest to lowest Amount.
IsWon = true — not a picklist
comparison against StageName.Amount DESC.IsWon is a formula-backed boolean that's true for exactly the
stage(s) flagged as "won" in Stage Settings — filtering on it is more robust than hardcoding
a Stage name like 'Closed Won', since org-specific stage names can vary.Write an Apex class UncontactedLeadsQuery with a method
getUncontactedLeads() that returns every Lead still at the default
"Open - Not Contacted" status, oldest first.
Status value.The support team wants a queue of Cases currently waiting on the customer to respond, oldest first, so nothing silently ages out.
AwaitingReplyCasesQuery with a method
getCasesAwaitingCustomerReply().Awaiting Customer Response.Write and run real Apex code right in your browser — instant pass/fail feedback, best-practice linting, and governor limit monitoring. No Salesforce org needed.
Create Free Account → Explore All ProblemsApexArena is a free, browser-based Salesforce Apex coding practice platform covering every major topic tested on the Salesforce Platform Developer I (PD1) and Platform Developer II (PD2) certification exams. All problems run directly in your browser with instant pass/fail feedback, best-practice linting (SOQL in loops, DML in loops, empty catch blocks), and governor limit monitoring — no Salesforce Developer Edition org required.
Related tutorials: Apex Triggers · SOQL · Batch Apex · Interview Q&A · Governor Limits