Advanced SOQL Statements - Getting Started with SOQL (2014)

Getting Started with SOQL (2014)

Chapter 3. Advanced SOQL Statements

In the previous chapter, we saw the basic SOQL statements that deal with one object in a SOQL statement. This chapter gives more information on how to write advanced SOQL statements. This chapter deals with querying the records for one or more objects in a single SOQL statement. In this case, there should be some relationship among the objects. In Salesforce.com, we cannot query the records from two or more objects if they don't have a relationship between them. The relationships that are available in Salesforce.com are lookup relationship and master-detail relationship.

Filtering a multiselect picklist field using the INCLUDES and EXCLUDES operators will be discussed in detail. In Chapter 2, Basic SOQL Statements, only the definition was given for the INCLUDES and EXCLUDES operators.

The grouping of records with more than one field using GROUP BY ROLLUP and GROUP BY CUBE will be explained here with examples. Sorting the records in both the ascending and descending orders together in a SOQL statement will also be further discussed.

Relationship queries

Relationship queries are mainly used to query the records from one or more objects in a single SOQL statement in Salesforce.com. As discussed earlier, we cannot query the records from more than one object without having a relationship between the objects.

Let us see an example for relationship queries with standard objects to query the records. The relationship between Account and Contact is a lookup. Account is the parent object, and Contact is the child object. Account can have multiple Contacts.

A sample query is given as follows:

SELECT Id, Name, (SELECT Id, Name FROM Contacts) FROM Account

The preceding query will retrieve all the accounts and their associated Contacts. The following screenshot shows the output of the SOQL execution:

Relationship queries

Let us see another example for relationship queries with custom objects to query the records. The relationship between Employee and Hobby is a master-detail relationship. Employee is the parent object, and Hobby is the child object. Employee can have multiple Hobbies.

A sample query is given as follows:

SELECT Employee_Name__c, (SELECT Id, Name FROM Hobbies__r) FROM Employee__c

The preceding query will retrieve all the names of the employees and their associated Hobbies. The following screenshot shows the output of the SOQL execution:

Relationship queries

To find out the name of the relationship, go to the objects' definition and select the relationship field. The Child Relationship Name option gives us the relationship name. The __r symbol should be added along with the child relationship name to query in the case of custom relationships. For standard relationships, we should not add __r. The following steps will help us to get the relationship name for relationship queries:

1. Navigate to Setup | Build | Create | Objects as shown in the following screenshot:

Relationship queries

2. Select the child object. In our example, Hobby is our child object as shown in the following screenshot:

Relationship queries

3. Select the relationship field:

Relationship queries

4. The Child Relationship Name option denotes the relationship name. We have to add __r to the child relationship name when querying the records using SOQL. In the case of a standard relationship, we need not add __r when we query the records using SOQL.

Relationship queries

Note

A custom relationship in Salesforce.com always ends with __r. But a standard relationship, which exists between the standard Salesforce.com objects, does not end with __r.

Filtering multiselect picklist values

The INCLUDES and EXCLUDES operators are used to filter the multiselect picklist field. The multiselect picklist field in Salesforce allows the user to select more than one value from the list of values provided.

Let us see a few examples of filtering the multiselect picklist values. Skills__c is a multiselect picklist field.

The INCLUDES operator

The INCLUDES operator is used to retrieve the records that contain any one of the specified values.

A sample query is given as follows:

SELECT Employee_Name__c, Skills__c FROM Employee__c WHERE Skills__c INCLUDES ('C', 'C#')

The preceding query will fetch the names of all the employees whose Skills match either with C or C#. The following screenshot is the output of the SOQL execution:

The INCLUDES operator

Let us see an example for including a null value.

A sample query is given as follows:

SELECT Employee_Name__c, Skills__c FROM Employee__c WHERE Skills__c EXCLUDES ('C', 'C#', '')

The preceding query will fetch the names of all employees whose Skills match either with C or C# and null. The following screenshot shows the output of the SOQL execution:

The INCLUDES operator

The EXCLUDES operator

The EXCLUDES operator is used to retrieve the records that do not contain any one of the specified values.

A sample query is given as follows:

SELECT Employee_Name__c, Skills__c FROM Employee__c WHERE Skills__c EXCLUDES ('C', 'C#')

The preceding query will fetch the names of all employees whose Skills do not match either with C or C#. The following screenshot shows the output of the SOQL execution:

The EXCLUDES operator

Let us see an example for excluding the null value.

A sample query is given as follows:

SELECT Employee_Name__c, Skills__c FROM Employee__c WHERE Skills__c EXCLUDES ('C', 'C#', '')

The preceding query will fetch the names of all the employees whose Skills do not match either with C or C# and null. The following screenshot shows the output of the SOQL execution:

The EXCLUDES operator

The escape sequences

An escape character is a character that invokes an alternative interpretation of the subsequent characters in a character sequence. The following table shows the list of escape sequences that can be used in the SOQL statements:

Sequence name

Description

\n or \N

New line

\r or \R

Carriage return

\t or \T

Tab

\f or \F

Form feed

\b or \B

Bell

\"

One double-quote character

\'

One single-quote character

\\

Backslash

The LIKE operator expression: \_

Matches a single underscore character (_)

The LIKE operator expression: \%

Matches a single percentage sign character (%)

The date formats

When querying the records using the date field or the date and time field in the SOQL statement, the date formats should be followed. The following table shows the list of date formats that can be used in the SOQL statements:

Format

Examples

YYYY-MM-DD

1999-01-01

YYYY-MM-DDThh:mm:ss+hh:mm

1999-01-01T23:01:01+01:00

YYYY-MM-DDThh:mm:ss-hh:mm

1999-01-01T23:01:01-08:00

YYYY-MM-DDThh:mm:ssZ

1999-01-01T23:01:01Z

The date literals

When querying the records using the date field in the SOQL statement, the date literals can be used. The following table shows the list of date literals that can be used in the SOQL statements:

Date literal

Sample query

YESTERDAY

SELECT Id FROM Employee__c WHERE Joining_Date__c = YESTERDAY

TODAY

SELECT Id FROM Employee__c WHERE Joining_Date__c > TODAY

TOMORROW

SELECT Id FROM Employee__c WHERE Joining Date__c = TOMORROW

LAST_WEEK

SELECT Id FROM Employee__c WHERE Joining_Date__c > LAST_WEEK

THIS_WEEK

SELECT Id FROM Employee__c WHERE Joining_Date__c < THIS_WEEK

NEXT_WEEK

SELECT Id FROM Employee__c WHERE Joining_Date__c = NEXT_WEEK

LAST_MONTH

SELECT Id FROM Employee__c WHERE Joining_Date__c > LAST_MONTH

THIS_MONTH

SELECT Id FROM Employee__c WHERE Joining_Date__c < THIS_MONTH

NEXT_MONTH

SELECT Id FROM Employee__c WHERE Joining_Date__c = NEXT_MONTH

LAST_90_DAYS

SELECT Id FROM Employee__c WHERE Joining_Date__c = LAST_90_DAYS

NEXT_90_DAYS

SELECT Id FROM Employee__c WHERE Joining_Date__c > NEXT_90_DAYS

LAST_N_DAYS:n

SELECT Id FROM Employee__c WHERE Joining_Date__c = LAST_N_DAYS:365

NEXT_N_DAYS:n

SELECT Id FROM Employee__c WHERE Joining_Date__c > NEXT_N_DAYS:15

THIS_QUARTER

SELECT Id FROM Employee__c WHERE Joining_Date__c = THIS_QUARTER

LAST_QUARTER

SELECT Id FROM Employee__c WHERE Joining_Date__c > LAST_QUARTER

NEXT_QUARTER

SELECT Id FROM Employee__c WHERE Joining_Date__c < NEXT_QUARTER

NEXT_N_QUARTERS:n

SELECT Id FROM Employee__c WHERE Joining_Date__c < NEXT_N_QUARTERS:2

LAST_N_QUARTERS:n

SELECT Id FROM Employee__c WHERE Joining_Date__c > LAST_N_QUARTERS:2

THIS_YEAR

SELECT Id FROM Employee__c WHERE Joining_Date__c = THIS_YEAR

LAST_YEAR

SELECT Id FROM Employee__c WHERE Joining_Date__c > LAST_YEAR

NEXT_YEAR

SELECT Id FROM Employee__c WHERE Joining_Date__c < NEXT_YEAR

NEXT_N_YEARS:n

SELECT Id FROM Employee__c WHERE Joining_Date__c < NEXT_N_YEARS:5

LAST_N_YEARS:n

SELECT Id FROM Employee__c WHERE Joining_Date__c > LAST_N_YEARS:5

THIS_FISCAL_QUARTER

SELECT Id FROM Employee__c WHERE Joining_Date__c = THIS_FISCAL_QUARTER

LAST_FISCAL_QUARTER

SELECT Id FROM Employee__c WHERE Joining_Date__c > LAST_FISCAL_QUARTER

NEXT_FISCAL_QUARTER

SELECT Id FROM Employee__c WHERE Joining_Date__c < NEXT_FISCAL_QUARTER

NEXT_N_FISCAL_QUARTERS:n

SELECT Id FROM Employee__c WHERE Joining_Date__c < NEXT_N_FISCAL_QUARTERS:6

LAST_N_FISCAL_QUARTERS:n

SELECT Id FROM Employee__c WHERE Joining_Date__c > LAST_N_FISCAL_QUARTERS:6

THIS_FISCAL_YEAR

SELECT Id FROM Employee__c WHERE Joining_Date__c = THIS_FISCAL_YEAR

LAST_FISCAL_YEAR

SELECT Id FROM Employee__c WHERE Joining_Date__c > LAST_FISCAL_YEAR

NEXT_FISCAL_YEAR

SELECT Id FROM Employee__c WHERE Joining_Date__c < NEXT_FISCAL_YEAR

NEXT_N_FISCAL_YEARS:n

SELECT Id FROM Employee__c WHERE Joining_Date__c < NEXT_N_FISCAL_YEARS:3

LAST_N_FISCAL_YEARS:n

SELECT Id FROM Employee__c WHERE Joining_Date__c > LAST_N_FISCAL_YEARS:3

Querying with the date fields

Let us see an example for querying with the date field using one of the date literals we just covered.

A sample query is given as follows:

SELECT Employee_Name__c, Joining_Date__c FROM Employee__c WHERE Joining_Date__c < LAST_MONTH

The preceding query will fetch the names of all the employees whose joining date values are less than the values for the current date last month. The following screenshot shows the output of the SOQL execution:

Querying with the date fields

Sorting in both the ascending and descending orders

Sometimes, we may get a chance to sort the records when we fetch these using the SOQL statements based on two fields, one field in the ascending order and another field in the descending order. The following sample query will help us to achieve this easily:

SELECT Name, Industry FROM Account ORDER By Name ASC, Industry DESC

Using the preceding SOQL query, the accounts will first be sorted by Name in the ascending order and then by Industry in the descending order. The following screenshot shows the output of the SOQL execution:

Sorting in both the ascending and descending orders

First, the records are arranged in the ascending order of the account's Name, and then it is sorted by Industry in the descending order.

Using the GROUP BY ROLLUP clause

The GROUP BY ROLLUP clause is used to add subtotals for aggregated data in query results. A query with a GROUP BY ROLLUP clause returns the same aggregated data as an equivalent query with a GROUP BY clause. It also returns multiple levels of subtotal rows. You can include up to three fields in a comma-separated list in a GROUP BY ROLLUP clause.

A sample query is given as follows:

SELECT City__c, State__c, COUNT(Employee_Name__c) Counts FROM Employee__c GROUP BY ROLLUP(City__c, State__c)

The following screenshot shows the output of the SOQL execution:

Using the GROUP BY ROLLUP clause

In the previous example, we saw both the statewise and citywise count. This GROUP BY ROLLUP clause will be very useful to us when we get a chance to work with the Visualforce charting feature.

Using the FOR REFERENCE clause

The FOR REFERENCE clause is used to find the date/time when a record has been referenced. The LastReferencedDate field is updated for any retrieved records. The FOR REFERENCE clause is used to track the date/time when a record has been referenced last while executing a SOQL query.

A sample query is given as follows:

SELECT City__c, State__c, LastReferencedDate FROM Employee__c FOR REFERENCE

When we execute the preceding query for the first time, it shows the last reference date of the record in the LastReferencedDate column. However, for the second time, all the records will show the same date and time (the date and time when we executed the query for the first time) for LastReferencedDate.

Using the FOR VIEW clause

The FOR VIEW clause is used to find the date when a record has been last viewed. The LastViewedDate field is updated for any retrieved records. The FOR VIEW clause is used to track the date when the record was viewed last while executing a SOQL query.

A sample query is given as follows:

SELECT City__c, State__c, LastViewedDate FROM Employee__c FOR VIEW

When we execute the preceding query for the first time, it shows the last viewed date of the record in the LastViewedDate column. However, for the second time, all the records will show the same date and time (the date and time when we executed the query for the first time) for LastViewedDate.

Using the GROUP BY CUBE clause

The GROUP BY CUBE clause is used to add subtotals for every possible combination of the grouped field in the query results. The GROUP BY CUBE clause can be used with aggregate functions such as SUM() and COUNT(fieldName). A SOQL query with a GROUP BY CUBE clause retrieves the same aggregated records as an equivalent query with a GROUP BY clause. It also retrieves additional subtotal rows for each combination of fields specified in the comma-separated grouping list as well as the grand total.

A sample query is given as follows:

SELECT City__c, State__c, GROUPING(City__c) CityGroup, GROUPING(State__c) StateGroup, COUNT(Id) IdCount FROM Employee__c GROUP BY CUBE(City__c, State__c)

The following screenshot shows the output of the SOQL execution:

Using the GROUP BY CUBE clause

Using the OFFSET clause

The OFFSET clause is used to specify the starting row number from which the records will be fetched. The OFFSET clause will be very useful when we implement pagination in the Visualforce page. The OFFSET clause along with LIMIT is very useful in retrieving a subset of the records. The OFFSET usage in SOQL has many limitations and restrictions. The limitation and guidelines for using OFFSET will be discussed in detail in Chapter 5, Limitations and Best Practices.

A sample query is given as follows:

SELECT Name FROM Account OFFSET 100

The preceding query will fetch all the accounts starting from the row number 101. The first 100 records will not be fetched.

Let us see an example for OFFSET along with LIMIT.

A sample query is given as follows:

SELECT Name FROM Account OFFSET 100 LIMIT 50

The preceding query will fetch all the accounts starting from row number 101 to 150. Only these 50 records will be fetched. The OFFSET clause along with LIMIT helps to create the pagination concept in the Visualforce page very easily. The offset calculation is done on the server side. So, we have to be very careful when implementing pagination since it fetches fresh data for each query call.

Salesforce.com recommends that we use the ORDER BY clause whenever we use OFFSET. Using the ORDER BY clause along with OFFSET ensures that the ordering of the result set is consistent.

Summary

In this chapter, we saw how to query the records from more than one object using the relationship queries. The steps to get the relationship name among objects were also provided. Querying the records using both standard relationship and custom relationship was also discussed.

Filtering multiselect picklist field values using the INCLUDES and EXCLUDES operators was explained. The grouping of records using GROUP BY ROLLUP and GROUP BY CUBE were also discussed.

To find the last viewed date of the record and to find the last referenced date of the record using FOR VIEW and FOR REFERENCE, respectively, were also explained. We also discussed pagination in the Visualforce page using OFFSET and LIMIT.

The next chapter deals with the functions that are available in SOQL. The functions help us to reuse the commands instead of writing conditions again and again.