Hello Trailblazers! Learning SOQL Queries is one of the first of the baby steps we took when started learning Salesforce. But there are some things that we overlooked, one of them is the
TYPEOF
clause in SOQL. Let us learn about that today!
Background
WhatId
. It is called
the
Polymorphic lookup field. The same type of field is used for the Owner lookup of any
record in Salesforce, where the Owner either can be a Group, a Queue, or a
User.
What.Type
in the where clause like below.
SELECT Id FROM Event WHERE What.Type IN ('Account', 'Opportunity')
The Problem
SELECT Id, What.CloseDate, What.Phone FROM Event WHERE What.Type IN ('Account', 'Opportunity')
Solution
TYPEOF
clause in SOQL.
SELECT TYPEOF What WHEN Account THEN Phone WHEN Opportunity THEN CloseDate ELSE Name END FROM Event
What
is Account, then we are
querying Phone
, if its an Opportunity then
CloseDate
and Name for others.
Sample Apex Code
Task[] tasks = [ SELECT TYPEOF What WHEN Account THEN Phone WHEN Opportunity THEN CloseDate ELSE Name END FROM Task ]; for(Task taskObj: tasks){ if(taskObj.WhatId != null){ String objType = taskObj.WhatId?.getSobjectType().getDescribe().getName(); if(objType == 'Opportunity'){ System.debug('CloseDate ' + taskObj.What.get('CloseDate')); } else if (objType == 'Account'){ System.debug('Phone ' + taskObj.What.get('Phone')); } else { System.debug('Name ' + taskObj.What.get('Name')); } } }
What.Type
and TYPEOF
can't be used for the Same field in one SOQL.
hi, thank you so much for this information. I've tried with my case and it worked perfectly. However I wanted to ask you if you know if it is possible to navigate to another object, also retrieving a value related to the object Opportunity. For example, in your example, using only the Opportunity:
ReplyDeleteTask[] tasks = [
SELECT
TYPEOF What
WHEN Opportunity THEN CloseDate, OwnerId.Username
ELSE Name
END
FROM Task
];
I was totally able to add this in a query, and it worked, the problem comes when I want to get this object:
if(objType == 'Opportunity'){
System.debug('Username' + taskObj.What.get('OwnerId.Username'));
How should I get this object?
Thank you again!
And, maybe I should add in my case I am working with Service Appointment and WorkOrder which both are standard objects, but I want to navigate from WorkOrder to Exploitation__r.(customfield) which as you can already tell is a custom object. Maybe this is why the What.get() is not working? thank you!
DeleteI will add my query here in case you need it for more information.
Delete[SELECT Id,
TYPEOF ParentRecord
WHEN WorkOrder THEN Id, Origin__c, Exploitation__c, Exploitation__r.SIT_Id__c, WorkOrderNumber
END
FROM ServiceAppointment WHERE Status =: Constants.SA_STATUS_DISPATCHED AND Id IN : saById.keySet()]
As you can already tell, Exploitation__r.SIT_Id__c is the custom object field I am navigating towards.
thank you again!
Hi Mo, I am glad that this post has helped you. I think you can get that data Exploitation__c expObj = (Exploitation__c) What.get('Exploitation__r');
Deletethen access it like expobj.SIT_Id__c
In the same way you can get the owner Id,
User usrObj = (User) taskObj.What.get('Owner');
access username using usrObj
let me know if this helps you.
it did indeed! thank you!
Delete