Top 55 SOQL Interview Questions

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.

Contents Covered In the Blog

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 Contact and pulling Account.Name).
  • Parent-to-Child (Downwards): Uses an inner query (subquery) to pull all related child records for a parent (e.g., querying Account and 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!

Author

  • Trigger Hours

    TriggerHours is a platform built on a simple idea: "The best way to grow is to learn together". We request seasoned professionals from across the globe to share their hard-won expertise, giving you the in-depth tutorials and practical insights needed to accelerate your journey. Our mission is to empower you to solve complex challenges and become an invaluable member of the Ohana.


Discover more from Trigger Hours

Subscribe to get the latest posts sent to your email.

Leave a Reply

Discover more from Trigger Hours

Subscribe now to keep reading and get access to the full archive.

Continue reading