A semi-join is a subquery on another object in an in clause that restricts the records returned by the primary query. Conversely, an anti-join is a subquery on another object in a nin clause that restricts the records returned.
If you filter by an ID field, you can create parent-to-child semi-joins and anti-join, such as Account to Contact or Account to Opportunity.
If you filter by a reference field, you can create child-to-child semi- or anti-joins, such as Contact to Opportunity. You can also create child-to-parent semi- or anti-joins, such as Opportunity to Account.
Semi-Join Filter
Semi-join filters help you narrow your query, such as returning only accounts whose opportunities match a specific criterion.
Semi-Join with ID Field
You can include a semi-join in a where argument. With the inq filter type for the ID field, you can restrict the records returned by the primary query.
This example returns accounts if an associated opportunity is closed won.
The previous query is similar to this SOQL statement.
SOQL statement with the IN clause
1SELECT Id, Name2FROM Account3WHERE Id4IN(5 SELECT AccountId6 FROM Opportunity7 WHERE StageName = 'Prospecting' and8 Probability = 20.09)
To restrict the records to show only those records with associated child records, use empty curly brackets {} or filter the Id on the subquery with ne: null.
Find accounts with billing in USA with associated contacts
The previous query is similar to this SOQL statement.
SOQL statement with WHERE and IN clauses
1SELECT Id, Subject, RecordType.Name2FROM Case3WHERE RecordTypeId IN4(SELECT Id5 FROM RecordType6 WHERE DeveloperName = 'My_Developer_Name'7)
Semi-Join with a Reference Field
A reference field contains an Id value that points to a record on another object. The name of a reference field ends with Id, such as AccountId or CaseId. For example, the AccountId field on a contact identifies a unique account record.
Some objects have WhoId or WhatId reference fields, which can point to one of several other objects. The WhoId field can point to a contact or lead. See Reference Field Type.
This example returns contact requests for all contacts whose first name starts with “R”.
The WhoId field in the semi-join is a polymorphic reference field because it can point to a contact or a lead. In this case, we restrict the subquery to contact records.
Anti-Join Filter
Anti-join filters help you narrow your query, such as returning only accounts that don’t match a certain criteria.
Anti-Join with ID Field
You can include an anti-join in a where argument. With the ninq filter type for the ID field, you can restrict the records returned by the primary query.
This example returns accounts that don’t have any open opportunities.
You can combine semi-join or anti-join clauses in a query. This example returns accounts that have open opportunities if the last name of the associated account starts with “G”.
Query accounts with multiple semi-joins on contacts and opportunities
The previous query is similar to this SOQL statement.
SOQL statement with multiple semi-joins
1SELECT Id, Name2FROM Account3WHERE Id IN4(5 SELECT AccountId6 FROM Contact7 WHERE LastName LIKE 'G%'8)9 AND Id IN10(11 SELECT AccountId12 FROM Opportunity13 WHERE isClosed = false14)
Evaluate Relationship Queries with Semi-Joins or Anti-Joins
You can create a semi-join or anti-join that evaluates a relationship query. This type of query returns object of one type based on criteria that applies to objects of another type.
This example returns accounts and their associated contacts if the contact lead source is Web.