Get Account lifetime value (sum of opportunities) and details - salesforce

I'm trying to get a table made of rows with Account details and the Sum of the Amount of the Opportunities for that Account.
SELECT Sum(Opportunity.Amount), Opportunity.AccountId FROM Opportunity GROUP BY AccountId
With this I get a simple list with the value I want and the AccountId.
Now I'd also like the Account details like PersonName.
How can I do that?
I've tried this:
SELECT Sum(Opportunity.Amount), Opportunity.AccountId, Account.PersonName
FROM Opportunity
GROUP BY Opportunity.AccountId
INNER JOIN Account WHERE Account.Id=AccountId
But I get Unknown error parsing query. Why?

I don't have Person Accounts enabled so you'll have to add your own fields but something like this should be good start.
SELECT AccountId, Account.Name, Account.Website, SUM(Amount)
FROM Opportunity
GROUP BY AccountId, Account.Name, Account.Website
Bit annoying that you have to list every field you want to see in GROUP clause too.
If you think you need this data in more places than this code (reports? list views?) then perhaps it's better idea to make a new "rollup summary" field on Account that'd aggregate for you the SUM(Amount)

I am guessing something like this:
SELECT Sum(o.Amount), a.AccountId, a.PersonName
FROM Opportunity o JOIN
Account a
ON a.Id = o.AccountId
GROUP BY a.AccountId, a.PersonName

Related

How to JOIN 2 Tables in SalesForce (SOQL)

I'm new to SalesForce and SOQL and was surprised that simple JOIN can become a real problem for me.
There are 2 Tables (Account and Intake__c) that I want to INNER JOIN. The only data I need from Account Table is Client Name (Name).
I was able to run 2 queries separately with no errors.
Account:
SELECT
a.Id,
a.Name
FROM Account AS a
Intake__c:
SELECT
i.Client_Id__c,
i.Intake_Id__c,
i.Intake_Name__c,
i.Intake_Status__c
FROM Intake__c AS i
However, when I try to join them, I get the error:
MALFORMED_QUERY: ERROR at Row:1:Column:151 unexpected token: 'JOIN'
SELECT
i.Client_Id__c,
a.Name,
i.Intake_Id__c,
i.Intake_Name__c,
i.Intake_Status__c
FROM Intake__c AS i
JOIN Account AS a
ON (i.Client_Id__c = a.Id)
SOQL syntax for joins is special, looks bit object-oriented. https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_relationships_and_custom_objects.htm
You probably need
SELECT Client_Id__r.Name, Intake_Id__c, Intake_Name__c, Intake_Status__c
FROM Intake__c
The "__r" bit is called relationship name and acts bit like a table alias in JOIN. You can travel via "dot" up to 5 times (see, "object-oriented").
And if you'd need a top-down approach (left outer join starting from account) it'd probably be something like
SELECT Id, Name,
(SELECT Intake_Status__c FROM Intakes__r)
FROM Account

Salesforce REST API SOQL get account for opportunies

I want to do a query for all my opportunities (or contacts or whatever) and then join in the account so I can get the name etc. I'm able to get it to work querying accounts and joining the opportunities, but not the other way around.
select Name, Id, (select Id, Name, CloseDate, StageName, Amount from Opportunities where ownerId = 'id') from Account
Is there a way to do the query on opportunities instead? I don't want to get all accounts and loop through to get the opportunity data. Should be a simple belongs to type relationship.
I've tried such queries as:
select Id, Name, CloseDate, StageName, Amount, (select Name, Id from Account) from Opportunity where ownerId = 'id'
But that gives me "Didn't understand relationship 'Account' in FROM part of query call."
Thanks!
For child->parent relationships you just use a dotted path to the fields you want, e.g.
Select id, Amount, CloseDate, Account.Name from Opportunity

SQL Sub Query when joining table

I am back to a similar issue I have had previously. It should be a simple thing, but cannot get my head around it. Here is an overview of the tables and what I am trying to achieve with this subquery. I am using SQL Server 2008.
Users
This contains a list of users
Login Audit
Contains a list of login attempts. It holds the userID and the loginDate (datetime field)
What I am trying to achieve
I want to be able to show rows of users and their last login date from the audit table.
Here is my query, that would make sense from a laymans perspective! ;-)
SELECT u.userID, u.fName, u.sName, l.loginDate
FROM Users AS u LEFT OUTER JOIN
(SELECT TOP (1) loginDate, userID
FROM LoginAudit) AS l ON l.userID = u.userID
WHERE (u.cliID = 1)
This just pulls back the last loginDatefor the last user that logged in. I wanted all of the users to come back regardless if they logged in or not.
Any assistance would be appreciated.
Thanks
nick
select a.userid, a.fName, a.sName,
max(b.loginDate)
from
users a
left outer join lastLogin b on a.userid = b.userid
group by a.userid, a.fName, a.sName
You want to replace your subquery with
SELECT userID, max(loginDate) as lastLogin FROM LoginAudit GROUP BY userID
And then replace "l.loginDate" in your main query with "l.lastLogin"
The functionality you want is provided by the MAX() function in an aggregate query, not the TOP() function.

Doing a join with SOQL

Here is my SOQL problem.
Query 1:
Select
c.Date_Joined__c,
c.Email,
c.FirstName,
c.LastName,
c.regcode__c
from Contact c WHERE c.regcode__c ='XXXXXXXXX'
Query 2:
Select
p.Account__c,
p.Date__c,
p.Points__c,
p.Description__c,
p.Code__c
from Points__c p where p.Account__c ='YYYYYYYYYYYY' and (p.Points__c > 0)
Order by p.Date__c DESC
The relationship between the two queries is that c.regcode__c will have the same value as p.Code__c.
I want to combine Query1 and Query2, so c.regcode__c = p.Code__c
I'm stuck, I can't seem to get the syntax right for SOQL.
Is it even possible to do joins in the API?
You can't really create a join per se but you can do some filtering using a syntax similar to this:
SELECT Id FROM Contact WHERE c.RegCode__c IN (SELECT p.Code__c FROM Account)
As long as the subquery in the WHERE clause is only returning a single value and codes is a filterable field this should work. Also, this doesn't work if you were trying to filter by the same object (i.e. Account to Account). You can add more criteria to the account side to match your example queries.
Again, this isn't a true join so you can't put the account fields from your subquery. But you can at least filter down your contacts.

Unable to understand the SQL code

I am finding it difficult to understand the code below. Can you give me a logical flow of how the code works ?
The question -
suppose you want to display the total number of orders placed by every customer in your Customers table. Orders are stored in the Orders table along with the appropriate customer ID.
The steps -
retrieve the list of customers from the customers table.
for each customer retrieved, count the number of associated orders in the Orders table.
The solution -
SELECT cust_name, cust_state,
(SELECT COUNT(*)
FROM Orders
WHERE Orders.cust_id = Customers.cust_id
)
AS order_nos
FROM Customers
ORDER BY cust_name
I am unable to understand the count(*) part inside the brackets. Please help me to figure it out.
Thanks.
It's just counting the number of rows. In this case, that's the number of orders per customer. The alternative COUNT(column_name) gives you the number of rows where column_name isn't null.
Equivalent without the sub-query (using a group instead):
SELECT cust_name, cust_state, COUNT(orders.cust_id) order_nos
FROM Customers
LEFT OUTER JOIN Orders on Customers.cust_id = Orders.cust_id
GROUP BY cust_name, cust_state
ORDER BY cust_name
It's called a correlated subquery. Essentially, for each customer, you're going to get a count of how many orders that customer has. The "magic" is in the WHERE Orders.cust_id = Customers.cust_id clause in the subquery. That's the part that correlates this result to your main query. It's saying "take the cust_id from the main query and now find the count of orders where the cust_id is that cust_id".

Resources