afv-library/skills/querying-soql/assets/relationship-queries.soql
sandipkumar-yadav 37aa84df42
feat: @W-22444026@ Introducing Core Skills, Datacloud Skills, Industries and Utility Skills. (#268)
* Migrating Core Salesforce Skills

* Updating pr comments

* updat reference

* Updating a skill

* Migrating Datacloud skills

* Migrating Industries cloud skills

* Validating - skills fixing

---------

Co-authored-by: Sandip Kumar Yadav <sandipkumar.yadav+sfemu@salesforce.com>
2026-05-14 19:32:15 +05:30

204 lines
7.5 KiB
Plaintext

/**
* RELATIONSHIP QUERY PATTERNS
*
* SOQL supports two types of relationships:
* 1. Child-to-Parent (dot notation) - Traverse up
* 2. Parent-to-Child (subquery) - Traverse down
*/
// ═══════════════════════════════════════════════════════════════════════════
// CHILD-TO-PARENT (DOT NOTATION)
// ═══════════════════════════════════════════════════════════════════════════
-- Basic parent field access
SELECT Id, Name, Account.Name, Account.Industry
FROM Contact
-- Multiple levels up (max 5 levels)
SELECT Id, Name,
Account.Name,
Account.Owner.Name,
Account.Owner.Manager.Name
FROM Contact
-- Filter by parent field
SELECT Id, Name, Email
FROM Contact
WHERE Account.Industry = 'Technology'
AND Account.AnnualRevenue > 1000000
-- Custom object parent relationship (__r suffix)
SELECT Id, Name, Custom_Parent__r.Name, Custom_Parent__r.Status__c
FROM Custom_Child__c
-- Standard lookup relationships
SELECT Id, Subject, WhatId, What.Name
FROM Task
WHERE What.Type = 'Account'
SELECT Id, CaseNumber, Account.Name, Contact.Name
FROM Case
WHERE Account.Industry = 'Healthcare'
// ═══════════════════════════════════════════════════════════════════════════
// PARENT-TO-CHILD (SUBQUERIES)
// ═══════════════════════════════════════════════════════════════════════════
-- Basic child records
SELECT Id, Name,
(SELECT Id, FirstName, LastName, Email FROM Contacts)
FROM Account
LIMIT 100
-- Multiple child relationships
SELECT Id, Name,
(SELECT Id, Name, Email FROM Contacts),
(SELECT Id, Name, Amount, StageName FROM Opportunities),
(SELECT Id, CaseNumber, Subject FROM Cases)
FROM Account
WHERE Industry = 'Technology'
LIMIT 50
-- Filtered child records
SELECT Id, Name,
(SELECT Id, Name, Amount
FROM Opportunities
WHERE StageName = 'Closed Won'
AND Amount > 10000
ORDER BY Amount DESC
LIMIT 5)
FROM Account
-- Custom child relationship (__r suffix, plural)
SELECT Id, Name,
(SELECT Id, Name, Status__c FROM Custom_Children__r)
FROM Custom_Parent__c
-- Order in subquery
SELECT Id, Name,
(SELECT Id, FirstName, LastName, CreatedDate
FROM Contacts
ORDER BY CreatedDate DESC
LIMIT 10)
FROM Account
// ═══════════════════════════════════════════════════════════════════════════
// COMMON RELATIONSHIP NAMES
// ═══════════════════════════════════════════════════════════════════════════
-- Account relationships
SELECT Id, Name,
(SELECT Id FROM Contacts), -- Standard
(SELECT Id FROM Opportunities), -- Standard
(SELECT Id FROM Cases), -- Standard
(SELECT Id FROM Notes), -- Standard
(SELECT Id FROM Attachments), -- Standard
(SELECT Id FROM Tasks), -- Standard
(SELECT Id FROM Events) -- Standard
FROM Account
LIMIT 10
-- Contact relationships
SELECT Id, Name,
(SELECT Id FROM Cases),
(SELECT Id FROM Tasks),
(SELECT Id FROM Events),
(SELECT Id FROM OpportunityContactRoles)
FROM Contact
LIMIT 10
-- Opportunity relationships
SELECT Id, Name,
(SELECT Id FROM OpportunityLineItems),
(SELECT Id FROM OpportunityContactRoles),
(SELECT Id FROM Tasks)
FROM Opportunity
LIMIT 10
// ═══════════════════════════════════════════════════════════════════════════
// SEMI-JOINS AND ANTI-JOINS
// ═══════════════════════════════════════════════════════════════════════════
-- Semi-join: Accounts WITH contacts
SELECT Id, Name FROM Account
WHERE Id IN (SELECT AccountId FROM Contact)
-- Semi-join: Accounts WITH opportunities over $100k
SELECT Id, Name FROM Account
WHERE Id IN (
SELECT AccountId FROM Opportunity
WHERE Amount > 100000
AND StageName = 'Closed Won'
)
-- Anti-join: Accounts WITHOUT contacts
SELECT Id, Name FROM Account
WHERE Id NOT IN (SELECT AccountId FROM Contact WHERE AccountId != null)
-- Anti-join: Accounts WITHOUT opportunities
SELECT Id, Name FROM Account
WHERE Id NOT IN (SELECT AccountId FROM Opportunity WHERE AccountId != null)
-- Anti-join: Leads not converted
SELECT Id, Name, Email FROM Lead
WHERE IsConverted = false
AND Id NOT IN (SELECT LeadId FROM Contact WHERE LeadId != null)
-- Multiple semi-joins
SELECT Id, Name FROM Account
WHERE Id IN (SELECT AccountId FROM Contact WHERE Email != null)
AND Id IN (SELECT AccountId FROM Opportunity WHERE Amount > 50000)
// ═══════════════════════════════════════════════════════════════════════════
// POLYMORPHIC RELATIONSHIPS (TYPEOF)
// ═══════════════════════════════════════════════════════════════════════════
-- Basic polymorphic query
SELECT Id, Subject, Who.Name, What.Name
FROM Task
WHERE Who.Type = 'Contact'
AND What.Type = 'Opportunity'
-- TYPEOF for conditional fields
SELECT
Id,
Subject,
TYPEOF What
WHEN Account THEN Name, Industry, AnnualRevenue
WHEN Opportunity THEN Name, Amount, StageName
WHEN Case THEN CaseNumber, Subject, Status
END
FROM Task
WHERE What.Type IN ('Account', 'Opportunity', 'Case')
-- TYPEOF with ELSE clause
SELECT
Id,
TYPEOF Owner
WHEN User THEN FirstName, LastName, Email
WHEN Group THEN Name
ELSE Name
END
FROM Account
// ═══════════════════════════════════════════════════════════════════════════
// ADVANCED PATTERNS
// ═══════════════════════════════════════════════════════════════════════════
-- Get accounts with contact count > 5 (requires Apex filtering)
-- Note: SOQL can't filter by aggregate of subquery
SELECT Id, Name, (SELECT Id FROM Contacts)
FROM Account
-- Then filter in Apex: WHERE Contacts.size() > 5
-- Get hierarchical data (self-reference)
SELECT Id, Name, ParentId, Parent.Name, Parent.Parent.Name
FROM Account
WHERE ParentId != null
-- Get users with role hierarchy
SELECT Id, Name, Manager.Name, Manager.Manager.Name
FROM User
WHERE IsActive = true
AND ManagerId != null