Trying to avoid Governor limits in no of SOQL queries - salesforce

i have 2 custom objects appointment_c and TimeDrive_c.
Appointment has fields
startdate__c
contact__c
TimeDrive__c has
Target_date__c
contact__c
CreatedDate
Here is what i need to do
I need to get all get all records with in a specific date range
select id, Target_date__c, Contact__c, Name, CreatedDate
from TimeDrive__c where Target_date__c >=:startdate and
Target_date__c <=:enddate
i need to loop through each record in this list and check if there are appointments for this contact which has startdate fall between targetdate and createddate
Here is the bit i have done till now
timeDriverLst = [select id, Target_date__c, Contact__c, Name, CreatedDate
from TimeDrive__c where Target_date__c >=:startdate and
Target_date__c <=:enddate ];
if(timeDriverLst.size() >0){
for(integer i =0; i < timeDriverLst.size(); i++)
{
mapTime.put(timeDriverLst[i].id, timeDriverLst[i]);
/* appLst = [Select Name, Contact__c from Appointment__c where (StartDate__c > = :timeDriverLst[i].CreatedDate
and StartDateTime__c <=:timeDriverLst[i].Target_date__c) and Contact__c = :timeDriverLst[i].Contact__c ];
*/
}
I know i shouldnt have a SOQL query within a for loop. How can i avoid this and achieve the requirement.

An ugly, but possibly usable solution: You could get all the contact ids from the time driver list and also find the earliest created date. Then you could pull out all the appointments whose contact id is in the contact id list and whose date is between the earliest created date and the target date. Then you would need to do a double loop, checking each appointment against each time driver. (Ordering the appts by contact or by date as you retrieve them might help here).

Related

Custom Label value not working in SOQL Query

I am trying to use custom label value in SOQL Query. Query is not accepting custom label value. it is expecting number.
Integer num_days = Integer.valueOf(System.Label.Num_of_Days);
Select id, name FROM contact WHERE LastModifiedDate >= LAST_N_DAYS :num_days
Thanks,
Anil Kumar
The full syntax of the "constant" you're using already has a semicolon in it: LAST_N_DAYS:7 etc. The whole thing has to be a text known at compile time, not just the part before :
This won't even compile, with 1 or 2 semicolons.
Integer x = 7;
List<Account> accs = [SELECT Id FROM Account WHERE CreatedDate = LAST_N_DAYS:x];
System.debug(accs);
You'll need to use dynamic SOQL or use your custom label to construct a date variable
String x = '7';
List<Account> accs = Database.query('SELECT Id FROM Account WHERE CreatedDate = LAST_N_DAYS:' + x);
System.debug(accs);
DateTime cutoff = System.today().addDays(- Integer.valueOf(x));
System.debug(cutoff);
System.debug([SELECT Id FROM Account WHERE CreatedDate <= TODAY AND CreatedDate >= :cutoff]);

Multiple AggregateResult Querys

Hi guys,
I'm currently trying to join two objects in a same query or result.
My question is if it's possible to show or debug the sum of FIELD A FROM LEAD + sum of FIELD B FROM two different Objects.
Here's an example I'm working on:
Btw I really appreciate your time and comments, and if i'm making a mistake pls let me know, thank you.
public static void example() {
String sQueryOne;
String sQueryTwo;
AggregateResult[] objOne;
AggregateResult[] objTwo;
//I tried to save the following querys into a sObject List
List<SObject> bothObjects = new List<SObject>();
sQueryOne = 'Select Count(Id) records, Sum(FieldA) fieldNA From Lead';
objOne = Database.query(sQueryOne);
sQueryTwo = 'Select Count(Id) records, Sum(FieldA) fieldNB From Opportunity';
objTwo = Database.query(sQueryTwo);
bothObjects.addAll(objOne);
bothObjects.addAll(objTwo);
for(sObject totalRec : bothObjects) {
//There's a Wrapper(className) I created which contains some variables(totalSum)
className finalRes = new className();
finalRes.totalSum = (Integer.valueOf(fieldNA)) + (Integer.valueOf(fieldNB));
System.debug('The sum is: '+finalRes.totalSum);
For example if I call a System debug with the previous variable finalRes.totalSum it's just showing the first value(fieldNA) duplicated.
The following debug shows the current values of the sObject List which I want to sum for example FIELD0 = from leads, FIELD0 = from Opportunities.
}
}
You access the columns in AggregateResult by calling get('columnAlias'). If you didn't specify an alias they'll be autonumbered by SF as expr0, expr1... When in doubt you can always go System.debug(results);
Some more info: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_SOQL_agg_fns.htm
This might give you some ideas:
List<AggregateResult> results = new List<AggregateResult>{
[SELECT COUNT(Id) records, SUM(NumberOfEmployees) fieldA, SUM(AnnualRevenue) fieldB FROM Account],
[SELECT COUNT(Id) records, SUM(Amount) fieldA, SUM(TotalOpportunityQuantity) fieldB FROM Opportunity],
[SELECT COUNT(Id) records, SUM(NumberOfEmployees) fieldA, SUM(AnnualRevenue) fieldB FROM Lead]
/* hey, not my fault these are only 2 standard numeric fields on Lead.
It doesn't matter that they're identical to Account fields, what matters is what their SUM(...) aliases are
*/
};
List<Decimal> totals = new List<Decimal>{0,0,0};
for(AggregateResult ar : results){
totals[0] += (Decimal) ar.get('records');
totals[1] += (Decimal) ar.get('fieldA');
totals[2] += (Decimal) ar.get('fieldB');
}
System.debug(totals); // (636, 8875206.0, 9819762558.0) in my dev org
(I'm not saying it's perfect, your wrapper class sounds like better idea or maybe even Map<String, Decimal>. Depends what are you going to do with the results)

PriceBookEntry required field missing when creating QuoteLineItems

I am kind of new to CPQ and have been trying to create a Quote Line Item with no success.
Opportunity OpportunityOne = [SELECT Id, PriceBook2Id FROM Opportunity WHERE
Id='0067F000008qOJzQAM' LIMIT 1];
Quote QuoteOne = [SELECT Id FROM Quote WHERE Name =:'TestQuote' LIMIT 1];
Product2 Product = [SELECT Id FROM Product2 WHERE Id
=: '01t7F0000032Y89QAE' LIMIT 1];
System.debug('Opportunity: '+OpportunityOne);
System.debug('Quote:'+QuoteOne);
System.debug('Product2:'+Product);
QuoteLineItem QuoteLineItemOne = new QuoteLineItem();
QuoteLineItemOne.QuoteId = QuoteOne.Id;
QuoteLineItemOne.Quantity = 100;
QuoteLineItemOne.UnitPrice = 2000;
QuoteLineItemOne.Product2Id = Product.Id;
insert QuoteLineItemOne;
Why does it keep saying price book entry is missing. It is annoying. Insert fails and I see no object requiring a price book entry field.
Please help me with this.
You'll need to roll the apex API version back to version 38 or earlier in order to create quote lines this way (using product2Id field). As you can see in the object reference from version 39 onwards you'll need to populate the pricebookentryId field instead and leave product2Id null. To get the pricebookEntryId you'll just need an extra query eg.
PriceBookEntry pbe = [SELECT id FROM PricebookEntry
WHERE Product2Id =: Product.id AND Pricebook2Id =: OpportunityOne.pricebook2Id LIMIT 1];
Then just set the pricebookentryId field on your quotelineitem instead of product2Id

filter by last 13 months

I have controller that is using a standardSetController to implement pagination. I want to filter by the trade date for the last 13 months. The date literals don't have a filter by Last_N_Months:N
Is there a way I can filter by the last 13 months?
Here is my current query:
setCtrl = new ApexPages.StandardSetController(Database.getQueryLocator([select TransactionType__c, TradeDate__c, ShareClass__c,
SettlementDate__c, Name, Fund__r.Name, Fund__r.Id, FirstTransaction__c, DCPosition__c, DBR__r.Name, DBR__r.Id, DBR__c,
Amount__c from Transaction__c where DBRPrimaryContact__r.Contact__c =: con.Id ORDER BY TradeDate__c ASC]));
If I can't filter by 13 months, what is the total number of records that can be returned in a query? Is it 2000? There can be a significant number of records for this object and I want to limit the results by 13 months of data. Once I have that result set, I want to add filtering by options.
Thanks for any help.
Try the code below for filtering Date range - you can programatically calculate exact date ranges
DATE d1 = date.today();
Date d2 = d1.addMonths(-13);
Integer d3 = d2.daysBetween(d1);
System.debug('*************' + [SELECT Id FROM Account WHERE CreatedDate >= :d2 AND CreatedDate <=:d1]);
For filtering by date you have LAST_90_DAYS or LAST_N_DAYS:90 like this
SELECT Id FROM Account WHERE CreatedDate = LAST_N_DAYS:90
More info in this link
And yes the total number retrieved in one query is 2000

SOQL - Querying for a list of users the current user is following

In my app I display a list of the current users. I request it like this:
Attempt 1
List<User> Following = [SELECT Id, Name, SmallPhotoUrl
FROM User
WHERE Id IN (
SELECT ParentId
FROM EntitySubscription
WHERE SubscriberId = :UserInfo.getUserId())
AND Id != :UserInfo.getUserId()
LIMIT 96];
This does exactly what it's supposed to when logged in as an admin but I found out that non-admins get an error:
Implementation restriction: EntitySubscription only allows security
evaluation for non-admin users when LIMIT is specified and at most
1000
OK, no big deal, I'll just slap a LIMIT on there like so:
Attempt 2
List<User> Following = [SELECT Id, Name, SmallPhotoUrl
FROM User
WHERE Id IN (
SELECT ParentId
FROM EntitySubscription
WHERE SubscriberId = :UserInfo.getUserId()
LIMIT 1000)
AND Id != :UserInfo.getUserId()
LIMIT 96];
Easy, right? WRONG. This gives the following:
expecting a right parentheses, found 'LIMIT'
OK...
I then tried breaking it out like so:
Attempt 3
List<EntitySubscription> sub = [SELECT ParentId
FROM EntitySubscription
WHERE SubscriberId = :UserInfo.getUserId()
LIMIT 1000];
List<Id> ids = new List<Id>();
for(EntitySubscription s : sub){
ids.add(s.ParentId);
}
List<User> Following = [SELECT Id, Name, SmallPhotoUrl
FROM User
WHERE Id IN (:ids)
AND Id != :UserInfo.getUserId()
LIMIT 96];
I crossed my fingers and...
Invalid bind expression type of LIST<Id> for column of type Id
Hmm, I'd seen examples where this seemed to be possible, such as on the developerforce boards, so I'm at a bit of a loss now.
So here we are. I need to select a list of user names and pictures that a particular user is following on Chatter. If there is a completely different way to go about it I'm open to it.
Try removing the parenthesis around the bind, i.e. change:
WHERE Id IN (:ids)
to:
WHERE Id IN :ids
And also simplify the query by just making sure that your list of IDs doesn't contain the current user's ID:
List<EntitySubscription> sub = [SELECT ParentId
FROM EntitySubscription
WHERE SubscriberId = :UserInfo.getUserId() AND ParentId != :UserInfo.getUserId()
LIMIT 1000];
Set<Id> ids = new Set<Id>();
for(EntitySubscription s : sub){
ids.add(s.ParentId);
}
Hope that helps!

Resources