Salesforce Relationship Queries: Parent-to-Child & Child-to-Parent SOQL with Examples
Salesforce Relationship Queries allow us to retrieve records from related objects using a single SOQL query. Instead of writing separate SOQL queries for related records, we can use relationship queries to navigate between parent and child objects.
Relationship queries are especially useful when working with Account, Contact, Opportunity, Case, and custom objects connected through Lookup or Master-Detail relationships.
In this Salesforce tutorial, we will understand:
- What are Salesforce Relationship Queries?
- Parent-to-Child SOQL queries
- Child-to-Parent SOQL queries
- Standard relationships
- Custom relationships
- Relationship query syntax
- Practical Apex examples
- Common mistakes
- Relationship Query interview questions
What Are Salesforce Relationship Queries?
A Relationship Query in Salesforce is a SOQL query that allows us to retrieve data from related objects.
For example, an Account can have multiple Contacts, Opportunities, and Cases.
Instead of querying the Account and then executing separate SOQL queries for Contacts, Opportunities, and Cases, we can retrieve the related records using relationship queries.
This can help reduce unnecessary SOQL queries within a transaction and makes the code easier to organize.
Why Use Relationship Queries?
Relationship queries are useful because Salesforce applications frequently work with related records.
For example:
- Account → Contacts
- Account → Opportunities
- Account → Cases
- Contact → Account
- Opportunity → Account
- Custom Parent → Custom Child
Instead of retrieving every related object independently, SOQL relationship syntax allows us to traverse these relationships.
Types of Salesforce Relationship Queries
Relationship queries can broadly be understood using four common combinations:
- Parent-to-Child Standard Relationship
- Parent-to-Child Custom Relationship
- Child-to-Parent Standard Relationship
- Child-to-Parent Custom Relationship
1. Parent-to-Child Relationship Query in Salesforce
In a Parent-to-Child relationship query, we start with the parent object and retrieve its related child records.
For example:
Account → Contacts
Account is the parent and Contact is the child.
Basic Syntax
SELECT Id, Name,
(SELECT Id, FirstName, LastName, Email
FROM Contacts)
FROM Account
The child query is called an Inner Query or Subquery.
Important Point About Child Relationship Names
When writing a parent-to-child relationship query, we use the Child Relationship Name in the inner query.
For many standard relationships, the relationship name is commonly the plural form of the child object.
For example:
SELECT Id, Name,
(SELECT Id, FirstName, LastName
FROM Contacts)
FROM Account
Here:
- Account is the parent object.
- Contacts is the child relationship name.
- The Contact records are returned inside the Account record.
Can We Use Multiple Child Queries?
Yes. A parent query can contain multiple child relationship subqueries when the relationships are available.
For example, an Account can have Contacts, Opportunities, and Cases.
SELECT Id, Name,
(SELECT Id, FirstName, LastName, Email
FROM Contacts),
(SELECT Id, Name, Amount, StageName
FROM Opportunities),
(SELECT Id, Subject, Description, Status
FROM Cases)
FROM Account
WHERE Name = 'Edge Communications'
This retrieves the Account and its related Contacts, Opportunities, and Cases.
Apex Example: Fetch Account and Related Contacts, Opportunities and Cases
Account acc = [
SELECT Id,
Name,
(SELECT Id, FirstName, LastName, Email, Phone
FROM Contacts),
(SELECT Id, Name, Amount, StageName
FROM Opportunities),
(SELECT Id, Subject, Description, Status
FROM Cases)
FROM Account
WHERE Name = 'Edge Communications'
LIMIT 1
];
System.debug('Account: ' + acc.Name);
for (Contact con : acc.Contacts) {
System.debug('Contact: ' + con.FirstName + ' ' + con.LastName);
}
for (Opportunity opp : acc.Opportunities) {
System.debug('Opportunity: ' + opp.Name);
}
for (Case c : acc.Cases) {
System.debug('Case: ' + c.Subject);
}
How Does This Code Work?
The outer query retrieves the Account record.
The inner queries retrieve the associated child records:
- Contacts → related Contact records
- Opportunities → related Opportunity records
- Cases → related Case records
The child records can then be accessed through the relationship properties of the parent record.
2. Child-to-Parent Relationship Query in Salesforce
A Child-to-Parent relationship query works in the opposite direction.
Instead of starting from the parent and retrieving children, we start from the child record and retrieve information from its parent.
For example:
Contact → Account
Contact is the child and Account is the parent.
Basic Syntax
SELECT Id,
FirstName,
LastName,
Email,
Account.Name,
Account.Rating
FROM Contact
The important syntax is:
ParentRelationshipName.FieldName
For a Contact's Account:
Account.Name
Account.Rating
Example: Contact and Associated Account Details
Contact con = [
SELECT Id,
FirstName,
LastName,
Email,
Account.Name,
Account.Rating
FROM Contact
WHERE Email = 'customer@example.com'
LIMIT 1
];
System.debug('Contact: ' + con.FirstName + ' ' + con.LastName);
System.debug('Account: ' + con.Account.Name);
System.debug('Rating: ' + con.Account.Rating);
Traversing More Than One Parent Relationship
One of the useful features of child-to-parent queries is that we can traverse through multiple parent relationships when the relationship path is supported.
For example, from Contact we can retrieve Account information and information from the Account's Owner.
SELECT Id,
FirstName,
LastName,
Email,
Account.Name,
Account.Owner.Name,
Account.Owner.Email
FROM Contact
WHERE Email = 'customer@example.com'
LIMIT 1
Here the relationship path is:
Contact
↓
Account
↓
Owner
Apex Example: Contact, Account and Account Owner
Contact con = [
SELECT Id,
FirstName,
LastName,
Email,
Account.Name,
Account.Owner.Name,
Account.Owner.Email
FROM Contact
WHERE Email = 'customer@example.com'
LIMIT 1
];
System.debug('Contact: ' + con.FirstName + ' ' + con.LastName);
System.debug('Account: ' + con.Account.Name);
System.debug('Account Owner: ' + con.Account.Owner.Name);
System.debug('Owner Email: ' + con.Account.Owner.Email);
3. Parent-to-Child Custom Relationship Query
Relationship queries also work with custom objects.
Suppose we have two custom objects:
- Hiring_Manager__c – Parent
- Position__c – Child
Assume Position has a Lookup or Master-Detail relationship to Hiring Manager.
In a parent-to-child query, we need to use the Child Relationship Name.
For a custom relationship, this commonly ends with __r.
Example
SELECT Id,
Name,
(SELECT Id, Name
FROM Positions__r)
FROM Hiring_Manager__c
Here:
- Hiring_Manager__c is the parent.
- Positions__r is the child relationship name.
Apex Example: Hiring Manager and Associated Positions
List<Hiring_Manager__c> managers = [
SELECT Id,
Name,
(SELECT Id, Name
FROM Positions__r)
FROM Hiring_Manager__c
];
for (Hiring_Manager__c manager : managers) {
System.debug('Hiring Manager: ' + manager.Name);
for (Position__c position : manager.Positions__r) {
System.debug('Position: ' + position.Name);
}
}
4. Child-to-Parent Custom Relationship Query
Custom relationships can also be traversed from the child to the parent.
Suppose:
Position__c
↓
Hiring_Manager__c
The relationship field on Position may look something like:
Hiring_Manager__c
The relationship name used in SOQL is generally:
Hiring_Manager__r
For example:
SELECT Id,
Name,
Hiring_Manager__r.Name
FROM Position__c
This allows us to retrieve Position information together with the associated Hiring Manager.
Standard vs Custom Relationship Queries
| Relationship | Example | SOQL Pattern |
|---|---|---|
| Parent → Child Standard | Account → Contact | Contacts |
| Child → Parent Standard | Contact → Account | Account.Name |
| Parent → Child Custom | Hiring Manager → Position | Positions__r |
| Child → Parent Custom | Position → Hiring Manager | Hiring_Manager__r.Name |
Relationship Query vs Separate SOQL Queries
Consider this approach:
Account acc = [
SELECT Id, Name
FROM Account
WHERE Name = 'Edge Communications'
LIMIT 1
];
List<Contact> contacts = [
SELECT Id, FirstName, LastName
FROM Contact
WHERE AccountId = :acc.Id
];
Here we execute separate SOQL queries.
Where the relationship allows it, we can retrieve the parent and child information together:
Account acc = [
SELECT Id,
Name,
(SELECT Id, FirstName, LastName
FROM Contacts)
FROM Account
WHERE Name = 'Edge Communications'
LIMIT 1
];
This can make the code cleaner and can help avoid unnecessary SOQL queries when the data can be retrieved through a relationship query.
Salesforce Governor Limits and Relationship Queries
Salesforce enforces governor limits to ensure that one transaction does not consume an excessive amount of shared resources.
One important limit developers need to consider is the number of SOQL queries executed during a transaction.
Relationship queries can help reduce the need for separate queries for related records. However, developers should still understand the limits associated with the complete query and the number of records returned.
Relationship queries are therefore one useful technique for writing more efficient Apex code, but they are not a replacement for overall governor-limit awareness.
Common Mistakes in Salesforce Relationship Queries
1. Using the Object API Name Instead of the Child Relationship Name
For custom parent-to-child queries, developers sometimes use the child object's API name instead of its configured child relationship name.
Always verify the relationship name in Salesforce Setup.
2. Forgetting __r in Custom Relationship Paths
When traversing a custom relationship from child to parent, the relationship name generally uses __r.
Hiring_Manager__r.Name
3. Querying Too Many Child Records
A relationship query can return a large amount of related data. Always consider filters and limits where appropriate.
4. Ignoring Null Parent Relationships
A child record may not always have a parent populated, depending on the relationship configuration. Your Apex code should account for null relationship values.
5. Performing SOQL Inside Loops
Relationship queries can help avoid unnecessary queries, but you should still avoid executing SOQL inside loops.
For example, avoid:
for (Account acc : accounts) {
List<Contact> contacts = [
SELECT Id, Name
FROM Contact
WHERE AccountId = :acc.Id
];
}
Instead, consider retrieving the related records through a relationship query when appropriate.
Salesforce Relationship Queries Interview Questions
What is a relationship query in Salesforce?
A relationship query is a SOQL query used to retrieve data from related objects through parent-child relationships.
What is Parent-to-Child SOQL?
Parent-to-child SOQL starts with a parent object and retrieves related child records using a subquery.
What is Child-to-Parent SOQL?
Child-to-parent SOQL starts with a child object and retrieves fields from its related parent using relationship notation such as Account.Name.
What is an Inner Query in Salesforce?
An inner query, also called a subquery, is used inside a parent SOQL query to retrieve related child records.
How do you query a parent field from a child object?
Use the relationship name followed by the field name.
SELECT Id, FirstName, Account.Name
FROM Contact
How do you query child records from a parent?
Use a child relationship subquery.
SELECT Id, Name,
(SELECT Id, FirstName, LastName
FROM Contacts)
FROM Account
What is __r in Salesforce SOQL?
__r is used when referencing a custom relationship name in relationship queries. The exact relationship name should be verified from the Salesforce object relationship configuration.
Key Takeaways
- Relationship queries allow Salesforce developers to retrieve related records through SOQL.
- Parent-to-child queries use inner queries or subqueries.
- Child-to-parent queries use relationship field notation.
- Standard relationships use Salesforce-defined relationship names.
- Custom relationships use configured relationship names, commonly involving __r.
- Relationship queries can help reduce unnecessary SOQL queries.
- Always consider governor limits and the number of records returned.
- Always verify custom child relationship names instead of assuming them.
Final Thoughts
Salesforce Relationship Queries are an important part of writing efficient Apex and SOQL. Once you understand the difference between Parent-to-Child and Child-to-Parent queries, working with related Salesforce records becomes much easier.
If you are learning Salesforce development, make sure you practice relationship queries using standard objects such as Account, Contact, Opportunity and Case, and then move on to custom objects and custom relationships.
Real-world Salesforce applications frequently require data from multiple related objects, so understanding relationship queries is an important skill for Salesforce Developers and is also a common topic in Salesforce technical interviews.
Frequently Asked Questions
Can Salesforce SOQL query parent and child records together?
Yes. Where the relationship supports it, SOQL can retrieve parent records and related child records using relationship subqueries.
Can we query multiple child relationships in one SOQL query?
Yes, multiple child relationship subqueries can be included in a parent query when the relationships are available and the resulting query complies with Salesforce limits.
What is the difference between __c and __r?
__c identifies a custom field or custom object API name, while __r is used for custom relationship references in SOQL.
Are relationship queries important for Salesforce interviews?
Yes. Parent-to-child and child-to-parent SOQL are commonly used in Salesforce development and are useful concepts to understand for Apex and SOQL interviews.