Tag Archives: SOQL

SOQL Group By Clause

GROUP BY clause is used in SOQL query to group set of records by the values specified in the field. We can perform aggregate functions using GROUP BY clause.

Aggregated functions for GROUP BY clause:

  • COUNT ()
  • COUNT (FIELD_NAME)
  • COUNT_DISTINCT ()
  • SUM ()
  • MIN ()
  • MAX ()

Example:

SELECT Industry, COUNT(Id) From Account GROUP BY Industry

GROUP BY With HAVING Clause:
GROUP BY HAVING Clause is used in SOQL to apply a condition based on a group field values.

Example:

SELECT Industry, COUNT(Id) From Account GROUP BY Industry HAVING Industry IN ('Agriculture','Manufacturing','Construction')

GROUP BY ROLLUP Clause:
GROUP BY ROLLUP Clause is used to add subtotals to get aggregates data in the query results. It returns multiple levels of subtotal rows. We can add up to three fields in a comma-separated list in GROUP BY ROLLUP Clause statement.

Example:

SELECT Industry, Type, COUNT(Id) From Account GROUP BY ROLLUP (Industry, Type)

GROUP BY CUBE Clause:
GROUP BY CUBE clause is used in SOQL query to add subtotals for all combinations of a grouped field in the query results.

Example:
The following query returns subtotals of accounts for each combination of Type and BillingCountry.

SELECT Type, BillingCountry,
GROUPING(Type) grpType, GROUPING(BillingCountry) grpCity,
COUNT(Id) accnts
FROM Account
GROUP BY CUBE(Type, BillingCountry)
ORDER BY GROUPING(Type), GROUPING(BillingCountry)

Some object fields have a field type that does not support grouping. You can’t include fields with these field types in a GROUP BY clause.

Following are the list of Groupable & Non-Groupable field types:

Groupable Field Types:

  • Id (Id)
  • Lookup (Id)
  • Checkbox (Boolean)
  • Phone (String)
  • Picklist (String)
  • Email (String)
  • Text (String)
  • Text Area (String)
  • URL (String)
  • Number (Int). Does not include custom fields, only standard Number fields with SOAP type int, like Account.NumberOfEmployees.
  • Date (date)
  • Direct cross-object references to groupable fields, up to 5 levels from the root object (SOQL limit), as in SELECT count(Id) FROM Contact GROUP BY Account.Parent.Parent.Parent.Parent.Name. Both custom and standard references are groupable.
  • Formulas of type Checkbox and Date, including cross-object formulas across standard and custom relationships.

Non-Groupable Field Types:

  • Auto Number (string)
  • Address Compound Fields
  • Number (double), including custom Number fields with or without decimal and regardless of scale.
  • Percent (double), including custom Percent fields with or without decimal and regardless of scale.
  • Currency (double), including custom Currency fields with or without decimal and regardless of scale.
  • Components of Address compound fields are groupable if their types otherwise allow it.
  • Geolocations, both custom and standard, and whether or not defined as having decimal places, including the compound field and components (location/double)
  • Long Text (string)
  • Rich Text (string)
  • Multi-Select Picklist (string)
  • Roll-Up Summary Fields (double), including COUNT rollups.
  • Encrypted Text Fields (Classic Encryption; string)
  • Date/Time (dateTime)
  • Time (time)
  • Formulas of types other than Checkbox and Date, including the otherwise-groupable String type.

Aggregate Functions Supported Field Types:

Data Type AVG() COUNT() COUNT_DISTINCT() MIN() MAX() SUM()
base64 No No No No No No
boolean No No No No No No
byte No No No No No No
date No Yes Yes Yes Yes No
dateTime No Yes Yes Yes Yes No
double Yes Yes Yes Yes Yes Yes
int Yes Yes Yes Yes Yes Yes
string No Yes Yes Yes Yes No
time No No No No No No
address No No No No No No
anyType No No No No No No
calculated Depends on data type* Depends on data type* Depends on data type* Depends on data type* Depends on data type* Depends on data type*
combobox No Yes Yes Yes Yes No
currency** Yes Yes Yes Yes Yes Yes
DataCategoryGroupReference No Yes Yes Yes Yes No
email No Yes Yes Yes Yes No
encryptedstring No No No No No No
location No No No No No No
ID No Yes Yes Yes Yes No
masterrecord No Yes Yes Yes Yes No
multipicklist No No No No No No
percent Yes Yes Yes Yes Yes Yes
phone No Yes Yes Yes Yes No
picklist No Yes Yes Yes Yes No
reference No Yes Yes Yes Yes No
textarea No Yes Yes Yes Yes No
url No Yes Yes Yes Yes No

Enforce Field-Level Security Permissions for SOQL Queries

  • In Spring ’19 Release Salesforce has introduced WITH SECURITY_ENFORCED clause, you can use this to enable checking for field- and object-level security permissions on SOQL SELECT queries, including subqueries and cross-object relationships.
  • Currently if you include a field in a SQOL query (Without WITH SECURITY_ENFORCED Clause) and a user doesn’t have access to that field, the field will be returned and can be used by the code without any exception, but the data to that user should not have access.
  • If you use WITH SECURITY_ENFORCED clause for same SOQL Select query, it will throw exception and no data will be returned.
  • This feature is tailored to Apex developers who have minimal development experience with security and to applications where graceful degradation on permissions errors isn’t required. The WITH SECURITY_ENFORCED clause is only available in Apex.
  • The WITH SECURITY_ENFORCED clause is only available in Apex. Using WITH SECURITY_ENFORCED in Apex classes or triggers with an API version earlier than 45.0 is not recommended.

Example:

If the Contact Email & Phone fields permission is not accessible to the user, it will throw an exception insufficient permissions and no data will return.

SELECT Id, Name, (SELECT Email, Phone FROM Contacts) FROM Account WITH SECURITY_ENFORCED

If the Account Website filed permission is not accessible to the user, it will throw an exception insufficient permissions and no data will return.

SELECT Id, Name, Website FROM Account WITH SECURITY_ENFORCED

SOQL Converting Time Zones in Date Functions

SOQL queries returns dateTime field values as Coordinated Universal Time (UTC) values. You can use convertTimezone() in a date function to convert dateTime fields to the user’s time zone.

Example 1:

SELECT DAY_ONLY(convertTimezone(CreatedDate)), SUM(Amount) FROM Opportunity GROUP BY DAY_ONLY(convertTimezone(CreatedDate))

Example 2:

SELECT Id, WhatId, Subject, CreatedDate From Task Where DAY_ONLY(convertTimezone(CreatedDate)) = TODAY

Note: You cannot use convertTimezone() without date function. The following query doesn’t work because there is no date function.

SELECT convertTimezone(CreatedDate) FROM Account

Check Case Owner is a User or Queue

Check Case Owner in Apex Class.

//Check object Id in Apex 
if(string.valueOf(c.OwnerId).startsWith('005')){
    //Owner is User       
}

if(string.valueOf(c.OwnerId).startsWith('00G')){
    //Owner is Queue
}

Check Case Owner in Apex Trigger.

//In Apex Trigger
for (Case objCase : Trigger.new) { 
    If (objCase.OwnerID.getsobjecttype() == User.sobjecttype) {
        /*Code if Owner is User*/
    }
    else{
        /*Code if Owner is Queue*/ 
    }
}

Check Case Owner by SOQL query.

//By Query Owner.Type Field
List<Case> caseList = [SELECT Id, CaseNumber, OwnerId, Owner.Name, Owner.Type FROM Case];

for (Case objCase : caseList){
    If (objCase.Owner.Type == User.sobjecttype) {
        /*Code if Owner is User*/
    }
    else{
        /*Code if Owner is Queue*/ 
    }
}

Check Case Owner in Process Builder.

//Check in Process Builder
BEGINS([Case].OwnerId, "005") //Check Owner is User
BEGINS([Case].OwnerId, "00G") //Check Owner is Queue