Salesforce SOQL String Functions not working (LEFT, SUBSTITUTE etc) - salesforce

I'm trying to get a list of domain names from email addresses using the Salesforce query language. This potentially really simple and something I would normally accomplish with split_part in postgresql, like:
SELECT split_part(Email, '#', 2)
FROM Lead
GROUP BY 1
I've been digging through the SOQL documentation and can't really find any standard string functions. However, there's this salesforce community answer: https://success.salesforce.com/answers?id=90630000000gi8EAAQ which uses LEFT, FIND and SUBSTITUTE. I tried something as simple as:
SELECT LEFT(Email, 3) FROM Lead limit 10
But get:
Error: MALFORMED_QUERY
Message: SELECT LEFT(Email, 3) FROM Lead limit 10
ERROR at Row:1:Column:17\nunexpected token: ','
Have these functions been deprecated?
I have lots of potential domain names and don't really want to query for pages and pages of every possible email address or I'll quickly hit my Salesforce API limit.

Those functions are not available in SOQL/SOSL. The link you provided refers to Custom Formula Fields. Are you trying to get the data using the UI or the API? Without knowing how you are extracting the data, the following are general suggestions:
You can create a formula field on your object called Email_Domain__c. Then, you can query or filter by that field.
You can also use custom formulas in Reports to filter your results.
Use Apex and/or Visualforce to extract/display/export the data.
Use the LIKE keyword to filter by domain name as in:
SELECT Email FROM LEAD WHERE Email LIKE '%gmail.com%'
The LIKE keyword is not efficient. https://trailhead.salesforce.com/en/modules/database_basics_dotnet/units/writing_efficient_queries

Related

Query users with a filter and expand results in unsupported query

I am trying to fetch a list of users from the Microsoft Graph API.
A lot of users don't have an email address, those users are systems users that I don't need.
So my query looks like /users?$filter=mail ne null
For another overview I need to show the manager of each user so I tried to add &$expand=manager. But doing so will result in an Unsupported Query.
When I remove the filter parameter it does work.
How can I only fetch relevant users and their managers in a single query?
Optionally I'd like to only receive the ID from managers, as an optimization. I only need the ID because I already fetched all users and their data. /users?$expand=manager($select=id) is what I was trying but I get the error Invalid $select properties.
If you want to use $select inside $expand to select the individual manager's properties, the $levels parameter is required, such as expand=manager($levels=max;$select=id). For more details, please refer to here
For example
https://graph.microsoft.com/v1.0/users?$expand=manager($levels=max;$select=id)
Update
If we want to use Not equals (ne) operators on the $filter query parameter, we must set the ConsistencyLevel header set to eventual and, with the exception of $search, use the $count query parameter (either as a URL segment or $count=true query string). For more details, please refer to here
For example
https://graph.microsoft.com/v1.0/users?$filter=mail ne null&&$expand=manager($levels=1;$select=id)&$count=true

MS Access, use query name as field default value

My department uses a software tool that can use a custom component library sourced from Tables or Queries in an MS Access database.
Table: Components
ID: AutoNumber
Type: String
Mfg: String
P/N: String
...
Query: Resistors
SELECT Components.*
FROM Components
WHERE Components.Type = "Resistors"
Query: Capacitors
SELECT Components.*
FROM Components
WHERE Components.Type = "Capacitors"
These queries work fine for SELECT. But when users add a row to the query, how can I ensure the correct value is saved to the Type field?
Edit #2:
Nope, can't be done. Sorry.
Edit #1:
As was pointed out, I may have misunderstood the question. It's not a wonky question after all, but perhaps an easy one?
If you're asking how to add records to your table while making sure that, for example, "the record shows up in a Resistors query if it's a Resistor", then it's a regular append query, that specifies Resisitors as your Type.
For example:
INSERT INTO Components ( ID, Type, Mfg )
SELECT 123, 'Resistors', 'Company XYZ'
If you've already tried that and are having problems, it could be because you are using a Reserved Word as a field name which, although it may work sometimes, can cause problems in unexpected ways.
Type is a word that Access, SQL and VBA all use for a specific purpose. It's the same idea as if you used SELECT and FROM as field or table names. (SELECT SELECT FROM FROM).
Here is a list of reserved words that should generally be avoided. (I realize it's labelled Access 2007 but the list is very similar, and it's surprisingly difficult to find an recent 'official' list for Excel VBA.)
Original Answer:
That's kind a a wonky way to do things. The point of databases is to organize in such a way as to prevent duplication of not only data, but queries and codes as well
I made up the programming rule for my own use "If you're doing anything more than once, you're doing it wrong." (That's not true in all cases but a general rule of thumb nonetheless.)
Are the only options "Resistors" and "Capacitors"? (...I hope you're not tracking the inventory of an electronics supply store...) If there are may options, that's even more reason to find an alternative method.
To answer your question, in the Query Design window, it is not possible to return the name of the open query.
Some alternative options:
As #Erik suggested, constrain to a control on a form. Perhaps have a drop-down or option buttons which the user can select the relevant type. Then your query would look like:
SELECT * FROM Components WHERE Type = 'Forms![YourFormName]![NameOfYourControl]'
In VBA, have the query refer to the value of a variable, foe example:
Dim TypeToDel as String
TypeToDel = "Resistor"
DoCmd.RunSQL "SELECT * FROM Components WHERE Type = '" & typeToDel'"
Not recommended, but you could have the user manually enter the criteria. If your query is like this:
SELECT * FROM Components WHERE Type = '[Enter the component type]'
...then each time the query is run, it will prompt:
Similarly, you could have the query prompt for an option, perhaps a single-digit or a code, and have the query choose the the appropriate criteria:
...and have an IF statement in the query criteria.
SELECT *
FROM Components
WHERE Type = IIf([Enter 1 for Resistors, 2 for Capacitors, 3 for sharks with frickin' laser beams attached to their heads]=1,'Resistors',IIf([Enter 1 for Resistors, 2 for Capacitors, 3 for sharks with frickin' laser beams attached to their heads]=2,'Capacitors','LaserSharks'));
Note that if you're going to have more than 2 options, you'll need to have the parameter box more than once, and they must be spelled identically.
Lastly, if you're still going to take the route of a separate query for each component type, as long as you're making separate queries anyway, why not just put a static value in each one (just like your example):
SELECT * FROM Components WHERE Type = 'Resistor'
There's another wonky answer here but that's just creating even more duplicate information (and more future mistakes).
Side note: Type is a reserved word in Access & VBA; you might be best to choose another. (I usually prefix with a related letter like cType.)
More Information:
Use parameters in queries, forms, and reports
Use parameters to ask for input when running a query
Microsoft Access Tips & Tricks: Parameter Queries
 • Frickin' Lasers

Salesforce - SOQL Use mod() or similar math functions in SELECT?

I'm trying to query all Opportunities that have a Price that's not a whole number (no decimals) or if its price is not multiple of 10.
Im trying to find prices like: U$S 34,801.23 - U$S 56,103.69 - U$S 50,000.12 etc
But not : U$S 49,500.00 - U$S 19,110.00 etc
There are a lot of opportunities in the database, and i can go through them by code but wanted to know if any of you can think of a way to achieve at leaast a part of this by query.
SOQL won't let you do any calculations. Check docs here and here:
You must supply a native value—other field names or calculations are
not permitted
Generally speaking it's fieldName = value or datefieldname > YESTERDAY (few special literals for date handling).
Easiest would be to create a formula field in the record (think about them like calculated columns in views in normal databases) with your logic. It could be of text type, call it "weird price" ;) Here's the complete formula functions reference - you have MOD(), IF(condition, true, false) etc goodies.
The only caveat is that you can't GROUP BY formula (there also tricks to bypass that ;))
So yeah - if it's one time thing with poor reusability - filter with code. If you can accept the low cost (formulas don't use storage but you might need them for other purposes) - create a field.

Working with columns having dot(.) in their name using GQL

I use Objectify for datastore operations in my GAE/Java application. I have used Objectify's #Embeded facility in a couple of places in my project. Objectify automatically flattens the nested objects within the entity marked by #Embeded notation using the . separator. Thus I have ended up with column names like entity.embededObject.Field
For example I have an entity 'Person' in my data store with two columns name and address.email.
I want to filter through Person in the datastore viewer by writing a simple GQL query.
But the following query fails with a syntax error:
SELECT * FROM Person where address.email='mail#gmail.com'
whereas the following works as it should
SELECT * FROM Person where name='Joe'
What am I doing wrong?
GQL currently doesn't support this - only 'word' characters are supported. You should definitely file this as a bug in the issue tracker.
Tested today, it is possible to run the following with backquotes
SELECT * FROM `your.kind`
I believe this holds true for any parameter, but please correct me if I am wrong.

SOQL query to traverse several levels on Task

I'm trying to write some apex code using this query and not getting anywhere:
List<Task> tasks = [SELECT id, whatid, who.account.parent.name FROM task WHERE who.account.parent.name LIKE 'Procter%'];
I'm not surprised this doesn't work, but can't seem to find documentation anywhere that explains how I would go about this. Does anyone have any idea? I'm trying to get all tasks linked to a contact linked to an account with a parent account of "procter and gamble"...
Looks like the options to "go up" in the mixed fields (the ones where Lookup goes to multiple objects like WhatId going to Account or Opportunity) are very limited. I was able to write "WHERE what.name LIKE 'Procter%' but not "WHERE what.parent.name LIKE 'Procter%'".
By the way I think it should be WhatId and not the WhoId (check out the Validation Rule editor for Tasks, try to insert fields "Contact/Lead ID" and "Opportunity/Account ID"). You will also see that you can't "go up" (or in case of this editor - "go right") on these fields while for some other fields you can explore the relation like for "CreatedBy.UserRole.Name".
Can you try this subquery instead?
[SELECT id, whatid FROM task WHERE whatid IN (SELECT Id FROM Account WHERE Parent.Name LIKE 'United%')]
WhatId and WhoID are polymorphic fields, so these fields do not support traversing multiple levels.
I had a similar requirement for hierarchal traversing, in my case i had to select the lead information associated with a task. What I had to do was first query for a list of tasks, then query for a list of leads based off those tasks, then use a wrapper class to combine the two lists into a custom object and display the object accordingly using visualforce. The wrapper class was certainly my answer to the equation since it seems you are in fact unable to query directly using the Who.Id.
Hope this helps!
The AccountID field on Tasks is populated by SF automatically for Contacts. Obviously, it is blank for Leads. So, if you want to get Account data you can just do something like this:
SELECT ID, Who.FirstName, Who.LastName, Account.Parent.Name FROM Task WHERE WhoID = '00Q12SDFUUALDLKJF'
Obviously, Account.Parent.Name is blank for Leads.

Resources