Alias in where query in SOQL - salesforce

I am trying to take the count from the object Lead using SOQL.
When I am hitting the below mention query, I am getting the results.
select 'Lead' as source_table,count(*) as source_count from Lead
But when I am trying to give where condition with this query, then it is throwing me the error.
select 'Lead' as source_table,count() as source_count from Lead where
CreatedDate > 2020-02-24T09:43:51Z
Is there anything that I am missing.

Your query is not a valid SOQL, where exactly are you doing it? In real Salesforce (Apex, developer console, Salesforce APIs) or do you work on some copy of data imported to MSSQL for example?
Even your basic form (select 'Lead' as source_table,count(*) as source_count from Lead) will not parse OK in SOQL. There's no AS keyword and no dummy columns.
Closest would be
SELECT COUNT(Id) source_count
FROM Lead
WHERE CreatedDate > 2020-02-24T09:43:51Z
There will be no artificial column with "Lead" in it. If you need some key-value thing across multiple database tables you'd have to process results in Apex, maybe make a helper class to store results, maybe a Map<String, Integer> would be enough. But if you're doing it as API access then much better idea would be to access the dedicated APIs
getUpdated REST API - has "updated" and "deleted" versions, if you really need "created" it's not that great unless you filter them out later somehow
record count across multiple objects - but it's really count in table, similar to Setup -> Storage Usage. No way to pass a WHERE clause
ask your SF admin to build a report that does what you need (you don't need details, just a count, right?), then access the results with Analytics API. Or even build the report on the fly: example

Related

How can I traverse through multiple related objects based on ID and return some related field?

I'm a little stuck.
I am trying to generate a report that determines whether anyone has made a manual change to certain fields within our order framework. I have figured out the proper fields and structures to audit, and even how to make the report, but I used a combination of extracts from the Dataloader and Excel xlookups to make it. Now, I'm being asked to find a way to automate the generation of the report, and I suspect that means I need to write a SOQL query to figure it out. I'm having trouble traversing multiple relationships based on these ID fields. Essentially, what I'm trying to do is make multiple "left joins" based on the 18 digit Salesforce IDs and extract some related piece of information from those other objects.
For example, if I'm starting with order_product_history (with a field OrderProductID to identify the order product) and I want to bring in "Product Name", I have to first match OrderProductID with the ID field in my order_product "table", then I have to match the Product2ID field in my order_product "table" with the ID in my product "table", then I have to get the matching Product Name as a column in my report:
Matching/Traversal Process
Desired Result
That's one example for one field. I also have to bring in things like User Name from the users "table", and order number from the orders table, but once I get the general idea, I think I'll be OK. I also want to filter the results to only include my Fee__c and UnitPrice fields, ignore the automated users and set a date filter--not sure if I have to do that using a WHERE clause just in my main query, or if I have to filter the subqueries as well.
I am not a programmer and I have no formal Salesforce training; I am just an analyst who is technically inclined and sort of fell into the role of Salesforce Admin. I am familiar with programming concepts and have been writing things using the flow application and have even dipped my toes into some Apex stuff, but it can be a bit of a struggle. I am not asking you to do my job for me and I am willing to work at the problem and learn; any help is appreciated. Sorry about the links; SO won't let me embed images yet.
There's high chance you don't have to write any code for it. I'll give you some tips, experiment a bit and edit the question or post new one?
This diagram might help: https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_erd_products.htm
Developer way
It's all about writing the right query. You can play with it in Developer Console or Workbench for example. Read up about relationship queries in SF.
https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_relationships_understanding.htm
https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_relationships_query_hist.htm
I don't have org with orders enabled but this should be a good start:
SELECT CreatedById, Created.Name,
Parent.Name, Parent.Product2.Name, Parent.Order.Name,
Field, OldValue, NewValue, CreatedDate
FROM OrderItemHistory
If it throws errors about "Parent" see if "OrderItem" will work. Once you have it - WHERE Field IN ('UnitPrice', 'Fee__c') AND CreatedDate = LAST_WEEK might be good next step. (dates can be filtered by date but there are few "constants" that are more human-readable too)
You could even export this with Data Loader, you just have to start the wizard on Order Product history table. But you can ignore the whole query creator and paste a query you've created.
Admin way
Have you ever created a report in Salesforce? There are self-paced trainings (for Lightning and Classic UI) and tons of YouTube videos. Get a feel of making few reports.
What you want might be doable with built-in report type (see if there's new report -> order product history). If nothing exciting - as admin you can make new report type in setup. For example Orders -> Order Products -> Order Product History. Screenshots from here might help.
Just wanted to update this for anyone looking for a solution in the future.
Turns out you can traverse these as a parent-child relationship in the SOQL query. Here's the query I ended up using:
SELECT CreatedBy.Name, FORMAT(CreatedDate), OrderItem.Order.OrderNumber, OrderItem.Product2.Name, OrderItem.Product2.ProductCode, Field, OldValue, NewValue
FROM OrderItemHistory
WHERE (Field = 'Fee__c' OR UnitPrice) AND (CreatedBy.Name != 'Integration User') AND (Created Date >= 2020-11-24T00:00:00.000Z) ORDER BY CreatedDate DESC

Querying Salesforce Object Column Names w/SOQL

I am using the Salesforce SOQL snap in a SnapLogic integration between our Salesforce instance and an S3 bucket.
I am trying to use a SOQL query in the Salesforce SOQL snap field "SOQL query*" to return the column names of an object. For example, I want to run a SOQL query to return the column names of the "Account" object.
I am doing this because SOQL does not allow "Select *". I have seen code solutions in Apex for this, but I am looking for a way to do it using only a SOQL query.
You want to query metadata? Names of available tables, names of columns you can see in each table, maybe types instead of real Account/Contact/... data, correct?
You might have to bump the version of the API up a bit, current is 47 / 48 so some objects might not be visible in your current one. Also - what API options you have? SOAP, REST? Is "Tooling API" an option? Because it has very nice official FieldDefinition table to pull this.
It's not perfect but this could get you started:
SELECT EntityDefinition.QualifiedApiName, QualifiedApiName, DataType
FROM FieldDefinition
WHERE EntityDefinition.QualifiedApiName IN ('Account', 'Contact', 'myNamespace__myCustomObject__c')
I don't see the table in the REST API reference but it seems to query OK in Workbench so there's hope.
Generally try to Google around about EntityDefinition, FieldDefinition, EntityParticle... For example this is a decent shot at learning which tables are visible to you:
SELECT KeyPrefix, QualifiedApiName, Label, IsQueryable, IsDeprecatedAndHidden, IsCustomSetting
FROM EntityDefinition
WHERE IsCustomizable = true AND IsCustomSetting = false
Or in a pinch you could try to see which fields your user has permission to query. It's bit roundabout way to do it but I have no idea which tables your connector can "see".
Starting from API version 51.0 there's the FIELDS() function available: it lets you query all fields of a given object similar to "SELECT *"
Example:
SELECT FIELDS(ALL) FROM User LIMIT 200
Reference:
https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_select_fields.htm

Get audit history records of any entity record as per CRM view

I want to display all audit history data as per MS CRM format.
I have imported all records from AuditBase table from CRM to another Database server table.
I want this table records using SQL query in Dynamics CRM format (as per above image).
I have done so far
select
AB.CreatedOn as [Created On],SUB.FullName [Changed By],
Value as Event,ab.AttributeMask [Changed Field],
AB.changeData [Old Value],'' [New Value] from Auditbase AB
inner join StringMap SM on SM.AttributeValue=AB.Action and SM.AttributeName='action'
inner join SystemUserBase SUB on SUB.SystemUserId=AB.UserId
--inner join MetadataSchema.Attribute ar on ab.AttributeMask = ar.ColumnNumber
--INNER JOIN MetadataSchema.Entity en ON ar.EntityId = en.EntityId and en.ObjectTypeCode=AB.ObjectTypeCode
--inner join Contact C on C.ContactId=AB.ObjectId
where objectid='00000000-0000-0000-000-000000000000'
Order by AB.CreatedOn desc
My problem is AttributeMask is a comma separated value that i need to compare with MetadataSchema.Attribute table's columnnumber field. And how to get New value from that entity.
I have already checked this link : Sql query to get data from audit history for opportunity entity, but its not giving me the [New Value].
NOTE : I can not use "RetrieveRecordChangeHistoryResponse", because i need to show these data in external webpage from sql table(Not CRM database).
Well, basically Dynamics CRM does not create this Audit View (the way you see it in CRM) using SQL query, so if you succeed in doing it, Microsoft will probably buy it from you as it would be much faster than the way it's currently handled :)
But really - the way it works currently, SQL is used only for obtaining all relevant Audit view records (without any matching with attributes metadata or whatever) and then, all the parsing and matching with metadata is done in .NET application. The logic is quite complex and there are so many different cases to handle, that I believe that recreating this in SQL would require not just some simple "select" query, but in fact some really complex procedure (and still that might be not enough, because not everything in CRM is kept in database, some things are simply compiled into the libraries of application) and weeks or maybe even months for one person to accomplish (of course that's my opinion, maybe some T-SQL guru will prove me wrong).
So, I would do it differently - use RetrieveRecordChangeHistoryRequest (which was already mentioned in some answers) to get all the Audit Details (already parsed and ready to use) using some kind of .NET application (probably running periodically, or maybe triggered by a plugin in CRM etc.) and put them in some Database in user-friendly format. You can then consume this database with whatever external application you want.
Also I don't understand your comment:
I can not use "RetrieveRecordChangeHistoryResponse", because i need to
show these data in external webpage from sql table(Not CRM database)
What kind of application cannot call external service (you can create a custom service, don't have to use CRM service) to get some data, but can access external database? You should not read from the db directly, better approach would be to prepare a web service returning the audit you want (using CRM SDK under the hood) and calling this service by external application. Unless of course your external app is only capable of reading databases, not running any custom web services...
It is not possible to reconstruct a complete audit history from the AuditBase tables alone. For the current values you still need the tables that are being audited.
The queries you would need to construct are complex and writing them may be avoided in case the RetrieveRecordChangeHistoryRequest is a suitable option as well.
(See also How to get audit record details using FetchXML on SO.)
NOTE
This answer was submitted before the original question was extended stating that the RetrieveRecordChangeHistoryRequest cannot be used.
As I said in comments, Audit table will have old value & new value, but not current value. Current value will be pushed as new value when next update happens.
In your OP query, ab.AttributeMask will return comma "," separated values and AB.changeData will return tilde "~" separated values. Read more
I assume you are fine with "~" separated values as Old Value column, want to show current values of fields in New Value column. This is not going to work when multiple fields are enabled for audit. You have to split the Attribute mask field value into CRM fields from AttributeView using ColumnNumber & get the required result.
I would recommend the below reference blog to start with, once you get the expected result, you can pull the current field value using extra query either in SQL or using C# in front end. But you should concatenate again with "~" for values to maintain the format.
https://marcuscrast.wordpress.com/2012/01/14/dynamics-crm-2011-audit-report-in-ssrs/
Update:
From the above blog, you can tweak the SP query with your fields, then convert the last select statement to 'select into' to create a new table for your storage.
Modify the Stored procedure to fetch the delta based on last run. Configure the sql job & schedule to run every day or so, to populate the table.
Then select & display the data as the way you want. I did the same in PowerBI under 3 days.
Pros/Cons: Obviously this requirement is for reporting purpose. Globally reporting requirements will be mirroring database by replication or other means and won't be interrupting Prod users & Async server by injecting plugins or any On demand Adhoc service calls. Moreover you have access to database & not CRM online. Better not to reinvent the wheel & take forward the available solution. This is my humble opinion & based on a Microsoft internal project implementation.

How to get the metadata of of a soql results query with no records returned?

I am new to Salesforce and I use Java Salesforce API (e.g., com.sforce.soap.metadata,com.sforce.ws). I know how to query through Java code using soql syntax.
At times, the soql does not return results, which makes it impossible to get details about the fields of the results, so I have need to get metadata on soql query regardless whether results are returned. If I have the following soql:
SELECT Name FROM Position_c WHERE Id NOT IN SELECT Position__c FROM Job_Application__c)
Can anyone tell me if it's possible to use Java to get the metadata on such query even if the query returns zero results ? It would be nice if you could include a short snippet of code showing how to do it.
I don't think there's a way to get it out of a 0 rows query. However you can look at the metadata for any object using the describesObject.
https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_describesobject.htm

Updating leads without an id in salesforce

I am new to apex development and I have a requirement where I need to update leads with a first and last name. There are no other ids. Any suggestions would be helpful
What is update context?
You can update records in Salesforce from several context:
Apex Trigger
Async Apex job
VisualForce pages
In different context the way for obtaining records may be different, but generally you need to query records using SOQL. It's hard to provide a good example without full requirements for your code, so it'll be something like that
Set<String> setOfNames = new Set<String>();
setOfNames.add('Tom James');
setOfNames.add('Shelly Brownell');
setOfNames.add('Bertha Boxer');
List<Lead> leadsForUpdate = [SELECT Id, fieldForUpdate__c
FROM Lead
WHERE Name IN: setOfNames];
criteria for SOQL query might be formed in any other way which meets your requirements

Resources