If you are stepping into a Salesforce Developer interview, you are guaranteed to be tested on SOQL (Salesforce Object Query Language). To pass a modern developer interview, you need to prove two things : First you understand the core theory, and you can apply that theory to real-world business scenarios without hitting governor limits.
We will dive into a definitive list Top 55 SOQL Interview Questions scenario-based, moving from basic syntax to advanced architect-level queries.
Foundation: Essential SOQL Interview Questions
Before an interviewer gives you a complex coding scenario, they will test your foundational understanding of how the Salesforce database operates.
1. What is SOQL and why is it important?
SOQL (Salesforce Object Query Language) is the native language used to read data directly from the Salesforce database. It is structurally similar to standard SQL but is highly optimized for Salesforce’s multi-tenant architecture. SOQL is critically important because it is the backbone of data retrieval for Apex classes, Lightning Web Components (LWCs), Batch jobs, and REST API integrations. Without SOQL, your code cannot interact with your Salesforce records.
2. Can we use SOQL in an Apex Trigger?
Absolutely. However, there is a strict golden rule: Never place a SOQL query inside a for loop. Because triggers often process records in bulk (up to 200 records at a time), a query inside a loop will quickly exhaust your governor limits. Instead, you must bulkify your triggers by gathering record IDs into a Set<Id>, performing a single SOQL query outside the loop, and storing the results in a Map.
3. What are the core Governor Limits for SOQL?
To prevent developers from monopolizing shared server resources, Salesforce enforces strict SOQL limits per transaction:
- Total number of SOQL queries issued: 100 for synchronous transactions, 200 for asynchronous transactions (Batch, Future, Queueable).
- Total number of records retrieved by SOQL queries: 50,000 records.
4. How do SOSL and SOQL differ?
SOQL (Query): Used when you know exactly which object the data resides in. It searches against specific database fields and returns a single list of sObjects.
SOSL (Search): Salesforce Object Search Language is used when you don’t know which object the data resides in. It performs a full-text search across multiple objects simultaneously (e.g., searching for “Acme” across Accounts, Contacts, and Leads at the same time) and returns a list of lists of sObjects.
5. What are Relationship Queries in SOQL?
Because Salesforce is a relational database, you often need data from related objects in a single query to save limits.
- Child-to-Parent (Upwards): Uses dot notation to pull data from a parent record (e.g., querying
Contactand pullingAccount.Name). - Parent-to-Child (Downwards): Uses an inner query (subquery) to pull all related child records for a parent (e.g., querying
Accountand pulling(SELECT Id FROM Contacts)).
Part 1: Basic SOQL Scenarios
These scenarios test your fundamental understanding of filtering, sorting, and basic logical operators.
6. The VP of Sales wants to see the top 5 largest Opportunities in the system based on their amount. How do you write this query?
The Trap: Forgetting that Amount can be null, which might skew sorting results if not handled properly.
SELECT Id, Name, Amount
FROM Opportunity
WHERE Amount != null
ORDER BY Amount DESC
LIMIT 5
7. We need to run a batch class on all Accounts created in the last 30 days. Write the SOQL query.
The Trap: Trying to use Apex to calculate System.today() - 30. Use SOQL Date Literals.
SELECT Id, Name, CreatedDate
FROM Account
WHERE CreatedDate = LAST_N_DAYS:30
8. Find all Contacts whose first name starts with ‘Jon’ so it should return ‘Jon’, ‘Jonathan’, ‘Jonny’, etc.
The Trap: Using = instead of LIKE, or putting the wildcard % in the wrong place.
SELECT Id, FirstName, LastName
FROM Contact
WHERE FirstName LIKE 'Jon%'
9. Query all Cases that are currently in ‘New’, ‘Working’, or ‘Escalated’ status.
The Trap: Writing multiple OR statements. Use the IN clause for cleaner code.
SELECT Id, CaseNumber, Status
FROM Case
WHERE Status IN ('New', 'Working', 'Escalated')
10. Get a list of all Opportunities, but filter out any that are ‘Closed Won’ or ‘Closed Lost’.
The Trap: Using != multiple times. Use NOT IN.
SELECT Id, Name, StageName
FROM Opportunity
WHERE StageName NOT IN ('Closed Won', 'Closed Lost')
11. Marketing wants a list of Leads where the Email address is missing.
The Trap: Checking for Email = '' (empty string). In Salesforce, a blank text field is generally evaluated as null.
SELECT Id, Name
FROM Lead
WHERE Email = null
12. Find all Accounts in the ‘Technology’ Industry that either have a Rating of ‘Hot’ OR an Annual Revenue over $1 Million.
The Trap: Forgetting the parentheses. If you mix AND and OR without parentheses, SOQL evaluates left-to-right, giving you incorrect data.
SELECT Id, Name
FROM Account
WHERE Industry = 'Technology'
AND (Rating = 'Hot' OR AnnualRevenue > 1000000)
13. Query all active users in the system.
The Trap: Wrapping the boolean in quotes like IsActive = 'true'. It must be a raw boolean.
SELECT Id, Name, Username
FROM User
WHERE IsActive = true
14. Sort all Accounts alphabetically by Industry, and then within each Industry, sort them by Annual Revenue from highest to lowest.
The Trap: Not knowing you can chain ORDER BY parameters separated by a comma.
SELECT Id, Name, Industry, AnnualRevenue
FROM Account
ORDER BY Industry ASC, AnnualRevenue DESC
15. You are building a custom LWC table that shows 20 records per page. How do you query for the ‘second page’ of Accounts?
The Trap: OFFSET has a maximum limit of 2,000. For anything larger, you must use standard set controllers or cursors.
SELECT Id, Name
FROM Account
ORDER BY Name
LIMIT 20 OFFSET 20
16. Find all Tasks that are due today.
The Trap: Using System.today() in Apex bindings when a native Date Literal is cleaner.
SELECT Id, Subject, ActivityDate
FROM Task
WHERE ActivityDate = TODAY
17. A user searched for ‘apple’, but the Account name is ‘APPLE’. Does WHERE Name = ‘apple’ find it?
Yes, it finds it. SOQL string comparisons are case-insensitive by default.
18. We need to query all Accounts associated with the ‘Enterprise’ Record Type.
Using RecordTypeId = '012x0000000...'. Hardcoding IDs guarantees your code will break during deployment.
SELECT Id, Name
FROM Account
WHERE RecordType.DeveloperName = 'Enterprise'
19. Sometimes integrations push empty strings (”) instead of null to text fields. How do you find Contacts where the Description is neither null nor an empty string?
The Trap: Only checking for null.
SELECT Id, Name
FROM Contact
WHERE Description != null AND Description != ''
20. Create a list of Accounts that the current user has recently viewed.
The Trap: Trying to query AccountHistory. Standard objects track this natively.
SELECT Id, Name
FROM Account
WHERE LastViewedDate != null
ORDER BY LastViewedDate DESC
21. You have an Apex variable String targetCity = ‘London’;. How do you use this in SOQL safely without string concatenation?
The Trap: String concatenation makes you vulnerable to SOQL Injection.
Answer: Use the : binding variable.
SELECT Id, Name
FROM Account
WHERE BillingCity = :targetCity
Part 2: Relationship Queries
These scenarios test your ability to navigate Salesforce’s relational database schema without writing multiple inefficient queries.
22. I need a list of all Contacts, but I only want the Contacts who work for an Account in the ‘Technology’ Industry. I also need the Account’s Name.
Common Pitfall: Querying the Account first, then using an Apex loop to query Contacts. Use dot notation to traverse upwards.
SELECT Id, Name, Account.Name, Account.Industry
FROM Contact
WHERE Account.Industry = 'Technology'
23. You have a custom object “Project__c” with a lookup to Account. How do you query the Project’s name and the related Account’s name?
Common Pitfall: Using Account.Name instead of Account__r.Name.
SELECT Id, Name, Account__r.Name
FROM Project__c
24. Extract all Accounts, and for each Account, include a list of all its related Opportunities.
Common Pitfall: Not knowing the plural “Child Relationship Name.”
SELECT Id, Name,
(SELECT Id, Name, StageName FROM Opportunities)
FROM Account
25. Extract all Accounts, and include a list of all related Project__c records.
Common Pitfall: Forgetting the __r suffix on the child relationship name in the FROM clause.
SELECT Id, Name,
(SELECT Id, Name FROM Projects__r)
FROM Account
26. From a Contact record, I need to know the First Name of the User who owns the related Account.
Common Pitfall: Thinking you can only go up one level. SOQL can traverse up to 5 levels of parent relationships!
SELECT Id, Name, Account.Owner.FirstName
FROM Contact
27. Query all Users who have the ‘System Administrator’ profile.
Common Pitfall: Querying the ProfileId directly requires you to hardcode the ID. Traverse the relationship instead.
SELECT Id, Name
FROM User
WHERE Profile.Name = 'System Administrator'
28. You need to query Tasks related to an Account. What field do you filter on?
Common Pitfall: Looking for an AccountId field. Tasks use polymorphic fields.
SELECT Id, Subject
FROM Task
WHERE WhatId = '001...'
29. Find the name of the current User’s Manager.
Common Pitfall: Creating a custom lookup. The User object has a standard ManagerId hierarchy field.
SELECT Id, Name, Manager.Name
FROM User
WHERE Id = :UserInfo.getUserId()
30. Can you put a WHERE clause on an inner query to filter the parent Accounts?
Common Pitfall: Thinking the inner query filters the Parent accounts. You can put a WHERE clause on an inner query, but it only filters the child records returned. It does NOT stop the parent Account from being returned. To filter the parent, you must use a Semi-Join (See Scenario 42).
Part 3: Aggregate Queries & Data Grouping
These questions evaluate your ability to let the database handle heavy mathematical lifting instead of relying on inefficient Apex processing.
31. How do you find the total dollar amount of all ‘Closed Won’ Opportunities?
The Trap: Doing the math in a for loop in Apex. Let the database calculate it.
SELECT SUM(Amount)
FROM Opportunity
WHERE StageName = 'Closed Won'
32. Find the highest expected revenue from any single Opportunity in the pipeline.
The Trap: Using ORDER BY ExpectedRevenue DESC LIMIT 1. While valid, MAX() is cleaner and performs better for pure aggregation.
SELECT MAX(ExpectedRevenue)
FROM Opportunity
WHERE IsClosed = false
33. What is our average deal size?
SELECT AVG(Amount)
FROM Opportunity
34. What is the difference between COUNT() and COUNT(FieldName)?
The Trap: Not knowing that COUNT(FieldName) ignores nulls.
Answer: COUNT() returns the total number of records. COUNT(Email) returns the number of records where the Email field is not null.
35. When you use SUM(Amount), the result is an AggregateResult object. How do you give that sum a readable name so you can easily extract it in Apex?
The Trap: Extracting via agg.get('expr0'). Use a SOQL alias! Answer:
SELECT SUM(Amount) totalRevenue
FROM Opportunity
36. Find all Opportunities that were closed in the year 2023.
The Trap: Doing complex date range filters (>= 2023-01-01 AND <= 2023-12-31). Answer:
SELECT Id, Name
FROM Opportunity
WHERE CALENDAR_YEAR(CloseDate) = 2023
37. Find all Contacts born in December so we can send holiday cards.
SELECT Id, Name
FROM Contact
WHERE CALENDAR_MONTH(Birthdate) = 12
38. Show me the count of Leads grouped by their Lead Source.
The Trap: Querying all leads and mapping them in Apex.
SELECT LeadSource, COUNT(Id)
FROM Lead
GROUP BY LeadSource
39. Following up on the grouped Leads by Source, now ONLY show the Lead Sources that have MORE than 50 Leads.
The Trap: Trying to use WHERE COUNT(Id) > 50. You must use HAVING to filter aggregated data.
SELECT LeadSource, COUNT(Id)
FROM Lead
GROUP BY LeadSource
HAVING COUNT(Id) > 50
40. We suspect we have duplicate Accounts. Write a query to find all Account Names that exist more than once.
The Trap: Exporting to Excel to find duplicates. Use SOQL!
SELECT Name, COUNT(Id)
FROM Account
GROUP BY Name
HAVING COUNT(Id) > 1
41. We need a query that groups Opportunities by LeadSource and calculates the SUM, but we ALSO need the grand total across all sources in the same result.
The Trap: Querying the sum separately.
Answer: ROLLUP adds a subtotal row to the aggregate results.
SELECT LeadSource, SUM(Amount)
FROM Opportunity
GROUP BY ROLLUP(LeadSource)
Part 4: Advanced SOQL Scenarios
These scenarios test deep optimization, architectural knowledge, security, and advanced platform behaviors.
42. Find all Accounts that have at least one Opportunity in the ‘Closed Won’ stage (Filter the Parents based on the Children).
The Trap: Using an inner query. A semi-join is required to filter the parent correctly without loading all the child records into memory.
SELECT Id, Name
FROM Account
WHERE Id IN (SELECT AccountId FROM Opportunity WHERE StageName = 'Closed Won')
43. Find all ‘Orphaned’ Accounts meaning Accounts that have absolutely zero Contacts associated with them.
The Trap: Querying everything and checking Contacts.size() == 0 in an Apex loop.
SELECT Id, Name
FROM Account
WHERE Id NOT IN (SELECT AccountId FROM Contact)
44. Find Accounts that DO have Contacts, but DO NOT have any Opportunities.
The Trap: Overcomplicating it. You can stack them.
SELECT Id, Name
FROM Account
WHERE Id IN (SELECT AccountId FROM Contact)
AND Id NOT IN (SELECT AccountId FROM Opportunity)
45. You wrote a SOQL query in an Apex class, but it throws a security review warning because it ignores Field-Level Security. How do you fix it at the query level?
The Trap: Writing lengthy Schema.SObjectType checks.
Answer: Append WITH SECURITY_ENFORCED.
SELECT Id, Name, AnnualRevenue
FROM Account
WITH SECURITY_ENFORCED
46. An admin accidentally deleted records. Write a query to find a specific Account, even if it is currently in the Recycle Bin.
The Trap: Deleted records are hidden from standard SOQL by default.
Answer: Append ALL ROWS.
SELECT Id, Name
FROM Account
WHERE Name = 'Acme Corp'
ALL ROWS
47. Two integrations might update the same Case at the exact same millisecond. How do you lock the record during your transaction?
The Trap: Apex doesn’t have traditional threading locks.
Answer: Use a pessimistic lock with FOR UPDATE.
SELECT Id, Status
FROM Case
WHERE Id = :caseId
FOR UPDATE
48. You have a multi-select picklist Regions__c. How do you find records that include ‘EMEA’?
The Trap: Using Regions__c = 'EMEA' (fails if they selected multiple values) or LIKE '%EMEA%' (risky if value substrings overlap).
SELECT Id, Name
FROM Account
WHERE Regions__c INCLUDES ('EMEA')
49. Find records where ‘APAC’ is strictly NOT selected in that multi-select picklist.
The Trap: Using !=.
SELECT Id, Name
FROM Account
WHERE Regions__c EXCLUDES ('APAC')
50. Your org uses Multi-Currency. A user in London views a report of US Opportunities. How do you query the Amount converted to the user’s personal currency?
The Trap: Doing the exchange rate math manually in Apex.
Answer: Use convertCurrency().
SELECT Id, convertCurrency(Amount)
FROM Opportunity
51. How do you query a Date or Currency field so that it formats automatically based on the running user’s locale settings (e.g., € vs $ or DD/MM vs MM/DD)?
The Trap: Writing massive Apex utility classes for formatting.
SELECT FORMAT(Amount), FORMAT(CloseDate)
FROM Opportunity
52. You are querying Tasks. The WhatId could be an Account or an Opportunity. If it’s an Account, return the Phone. If it’s an Opportunity, return the Amount. Write the query.
The Trap: Executing multiple queries and sorting it out in Apex. You can do this in one query using TYPEOF.
SELECT Id, Subject,
TYPEOF What
WHEN Account THEN Phone
WHEN Opportunity THEN Amount
END
FROM Task
53. Find all users who successfully logged in today.
The Trap: Looking at the User object directly.
SELECT UserId, LoginTime
FROM LoginHistory
WHERE LoginTime = TODAY AND Status = 'Success'
54. An auditor wants to know every time an Account’s Industry field was changed. How do you query this?
The Trap: Querying the Account object. You must query the history tracking table.
SELECT AccountId, OldValue, NewValue, CreatedDate, CreatedById
FROM AccountHistory
WHERE Field = 'Industry'
55. You are querying Salesforce Knowledge Articles, but you only want articles categorized under ‘IT Support’ and its subcategories.
The Trap: Searching for a normal lookup field. Knowledge requires specific syntax.
SELECT Title, Summary
FROM KnowledgeArticleVersion
WITH DATA CATEGORY Department__c BELOW IT_Support__c
Keep practicing, and go crush that interview!
Got a tricky SOQL interview question you couldn’t solve? Drop it in the comments below and the Triggerhours community will help you out!
Discover more from Trigger Hours
Subscribe to get the latest posts sent to your email.