Newer Version Available
Comparison Operators
The following table lists the comparisonOperator values that are used in fieldExpression syntax.
| Operator | Name | Description |
|---|---|---|
| = | Equals | Expression is true if the value in the fieldName equals the value in the expression. |
| != | Not equals | Expression is true if the value in the fieldName doesn’t equal the specified value. |
| < | Less than | Expression is true if the value in the fieldName is less than the specified value. |
| <= | Less or equal | Expression is true if the value in the fieldName is less than or equal to the specified value. |
| > | Greater than | Expression is true if the value in the fieldName is greater than the specified value. |
| >= | Greater or equal | Expression is true if the value in the fieldName is greater than or equal to the specified value. |
| LIKE | Like | Expression is true if the value in the fieldName matches the characters of the text string in the specified value. The text string
in the specified value must be enclosed in single quotes. The LIKE operator is supported for string fields only. The operator provides a mechanism for matching partial text strings and includes support for: .
This example query matches Appleton, Apple, and Appl, but not Bappl.
|
| IN | IN | If the value equals any one of the values in a WHERE clause. The string values for IN must be in
parentheses and surrounded by single quotes. You can query values in a field where another field on the same object has a specified set of values, using IN. For example: You can also use IN and NOT IN for semi-joins and anti-joins when querying on ID (primary key) or reference (foreign key) fields. |
| NOT IN | NOT IN | If the value doesn’t equal any of the values in a WHERE clause. The string values for NOT IN must
be in parentheses and surrounded by single quotes. For example: |
| INCLUDES EXCLUDES | Applies only to multi-select picklists. See Query Multi-Select Picklists. |
Semi-Joins with IN and Anti-Joins with NOT IN
A semi-join is a subquery on another object in an IN clause to restrict the records returned. An anti-join is a subquery on another object in a NOT IN clause to restrict the records returned. You can create more complex queries by replacing the list of values in the IN or NOT IN clause with a subquery. The subquery can filter by ID (primary key) or reference (foreign key) fields.
Sample uses of semi-joins and anti-joins include:
- Get all contacts for accounts that have an opportunity with a particular record type.
- Get all open opportunities for accounts that have active contracts.
- Get all open cases for contacts that are the decision maker on an opportunity.
- Get all accounts that don’t have any open opportunities.
If you filter by an ID field, you can create parent-to-child semi- or anti-joins, such as Account to Contact. If you filter by a reference field, you can create child-to-child semi- or anti-joins, such as Contact to Opportunity, or child-to-parent semi- or anti-joins, such as Opportunity to Account.
- ID field Semi-Join
- You can include a semi-join in a WHERE clause. For example, the following query returns account IDs if an
associated opportunity is lost:
1SELECT Id, Name 2FROM Account 3WHERE Id IN 4 ( SELECT AccountId 5 FROM Opportunity 6 WHERE StageName = 'Closed Lost' 7 )This example is a parent-to-child semi-join from Account to Opportunity. Notice that the left operand, Id, of the IN clause is an ID field. The subquery returns a single field of the same type as the field to which it’s compared. For restrictions that prevent unnecessary processing of semi-join queries, see Considerations.
- Reference Field Semi-Join
-
The following query returns task IDs for all contacts in Twin
Falls:
1SELECT Id 2FROM Task 3WHERE WhoId IN 4 ( 5 SELECT Id 6 FROM Contact 7 WHERE MailingCity = 'Twin Falls' 8 )Notice that the left operand, WhoId, of the IN clause is a reference field. An interesting aspect of this query is that WhoId is a polymorphic reference field as it can point to a contact or a lead. The subquery restricts the results to contacts.
- ID field Anti-Join
- The following query returns account IDs for all accounts that don’t have any open
opportunities:
1SELECT Id 2FROM Account 3WHERE Id NOT IN 4 ( 5 SELECT AccountId 6 FROM Opportunity 7 WHERE IsClosed = false 8 ) - Reference Field Anti-Join
-
The following query returns opportunity IDs for all contacts whose source isn’t Web:
1SELECT Id 2FROM Opportunity 3WHERE AccountId NOT IN 4 ( 5 SELECT AccountId 6 FROM Contact 7 WHERE LeadSource = 'Web' 8 )This example is a child-to-child anti-join from Opportunity to Contact.
- Multiple Semi-Joins or Anti-Joins
- You can combine semi-join or anti-join clauses in a query. For example, the following query returns account IDs that have open opportunities if the last name of the contact
associated with the account is like the last name “Apple”:
1SELECT Id, Name 2FROM Account 3WHERE Id IN 4 ( 5 SELECT AccountId 6 FROM Contact 7 WHERE LastName LIKE 'apple%' 8 ) 9 AND Id IN 10 ( 11 SELECT AccountId 12 FROM Opportunity 13 WHERE isClosed = false 14 ) - Semi-Joins or Anti-Joins Evaluating Relationship Queries
- You can create a semi-join or anti-join that evaluates a relationship query in a SELECT clause. For example, the following query returns opportunity IDs and their related line items if the opportunity's line item total value
is more than $10,000:
1SELECT Id, (SELECT Id from OpportunityLineItems) 2FROM Opportunity 3WHERE Id IN 4 ( 5 SELECT OpportunityId 6 FROM OpportunityLineItem 7 WHERE totalPrice > 10000 8 )
Considerations for Semi-Join and Anti-Join Queries
Because a great deal of processing work is required for semi-join and anti-join queries, Salesforce imposes the following restrictions to maintain the best possible performance:
-
Basic limits:
- You can’t use more than two IN or NOT IN statements per WHERE clause.
- You can’t use the NOT operator as a conjunction with semi-joins and anti-joins. Using it converts a semi-join to an anti-join, and the reverse. Instead of using the NOT operator, write the query in the appropriate semi-join or anti-join form.
-
Main query limits:
The following restrictions apply to the main WHERE clause of a semi-join or anti-join query:
- The left operand must query a single ID (primary key) or reference (foreign key) field. The selected field in a subquery can be a reference field. For
example:
1SELECT Id 2 FROM Idea 3 WHERE (Id IN (SELECT ParentId FROM Vote WHERE CreatedDate > LAST_WEEK AND Parent.Type='Idea')) - The left operand can't use relationships. For example, the following semi-join query is invalid due to the Account.Id relationship
field:
1SELECT Id 2FROM Contact 3WHERE Account.Id IN 4 ( 5 SELECT ... 6 )
- The left operand must query a single ID (primary key) or reference (foreign key) field. The selected field in a subquery can be a reference field. For
example:
-
Subquery limits:
- A subquery must query a field referencing the same object type as the main query.
- There’s no limit on the number of records matched in a subquery. Standard SOQL query limits apply to the main query.
-
The selected column in a subquery must be a foreign key field, and can’t traverse relationships. This limit means that you can’t use dot notation in
a selected field of a subquery. For example, the following query is valid:
1SELECT Id, Name 2FROM Account 3WHERE Id IN 4 ( 5 SELECT AccountId 6 FROM Contact 7 WHERE LastName LIKE 'Brown_%' 8 )Using Account.Id (dot notation) instead of AccountId isn’t supported. Similarly, subqueries like Contact.AccountId FROM Case are invalid.
- You can’t query on the same object in a subquery as in the main query. You can write such self semi-join queries without using semi-joins or anti-joins. For
example, the following self semi-join query is invalid:
1SELECT Id, Name 2FROM Account 3WHERE Id IN 4 ( 5 SELECT ParentId 6 FROM Account 7 WHERE Name = 'myaccount' 8 )Rewrite the query in a valid form, for example:1SELECT Id, Name 2FROM Account 3WHERE Parent.Name = 'myaccount' - You can’t nest a semi-join or anti-join statement in another semi-join or anti-join statement.
- You can’t use semi-joins and anti-joins in a HAVING clause.
- You can use semi-joins and anti-joins in the main WHERE statement, but not in a subquery WHERE
statement. For example, the following query is valid:
1SELECT Id 2 FROM Idea 3 WHERE (Idea.Tit’sle LIKE 'Vacation%') 4AND (Idea.LastCommentDate > YESTERDAY) 5AND (Id IN (SELECT ParentId FROM Vote 6 WHERE CreatedById = '005x0000000sMgYAAU' 7 AND Parent.Type='Idea'))The following query is invalid since the nested query is an extra level deep:
1SELECT Id 2 FROM Idea 3 WHERE 4 ((Idea.Title LIKE 'Vacation%') 5 AND (CreatedDate > YESTERDAY) 6 AND (Id IN (SELECT ParentId FROM Vote 7 WHERE CreatedById = '005x0000000sMgYAAU' 8 AND Parent.Type='Idea') 9 ) 10 OR (Idea.Title like 'ExcellentIdea%')) - You can’t use subqueries with OR.
- COUNT, FOR UPDATE, ORDER BY, and LIMIT aren’t supported in subqueries.
- The following objects aren’t currently supported in subqueries:
- ActivityHistory
- Attachments
- Event
- Note
- OpenActivity
- Tags (AccountTag, ContactTag, and all other tag objects)
- Task