SOQL - Convert Date To Owner Locale - sql-server

We use the DBAmp for integrating Salesforce.com with SQL Server (which basically adds a linked server), and are running queries against our SF data using OPENQUERY.
I'm trying to do some reporting against opportunities and want to return the created date of the opportunity in the opportunity owners local date time (i.e. the date time the user will see in salesforce).
Our dbamp configuration forces the dates to be UTC.
I stumbled across a date function (in the Salesforce documentation) that I thought might be some help, but I get an error when I try an use it so can't prove it, below is the example useage for the convertTimezone function:
SELECT HOUR_IN_DAY(convertTimezone(CreatedDate)), SUM(Amount)
FROM Opportunity
GROUP BY HOUR_IN_DAY(convertTimezone(CreatedDate))
Below is the error returned:
OLE DB provider "DBAmp.DBAmp" for linked server "SALESFORCE" returned message "Error 13005 : Error translating SQL statement: line 1:37: expecting "from", found '('".
Msg 7350, Level 16, State 2, Line 1
Cannot get the column information from OLE DB provider "DBAmp.DBAmp" for linked server "SALESFORCE".
Can you not use SOQL functions in OPENQUERY as below?
SELECT
*
FROM
OPENQUERY(SALESFORCE,'
SELECT HOUR_IN_DAY(convertTimezone(CreatedDate)), SUM(Amount)
FROM Opportunity
GROUP BY HOUR_IN_DAY(convertTimezone(CreatedDate))')
UPDATE:
I've just had some correspondence with Bill Emerson (I believe he is the creator of the DBAmp Integration Tool):
You should be able to use SOQL functions so I am not sure why you are
getting the parsing failure. I'll setup a test case and report back.
I'll update the post again when I hear back. Thanks

A new version of DBAmp (2.14.4) has just been released that fixes the issue with using ConvertTimezone in openquery.
Version 2.14.4
Code modified for better memory utilization
Added support for API 24.0 (SPRING 12)
Fixed issue with embedded question marks in string literals
Fixed issue with using ConvertTimezone in openquery
Fixed issue with "Invalid Numeric" when using aggregate functions in openquery

I'm fairly sure that because DBAmp uses SQL and not SOQL, SOQL functions would not be available, sorry.
You would need to expose this data some other way. Perhaps it's possible with a Salesforce report, web-service, or compiling the data through the program you are using to access the (DBAmp) SQL Server.
If you were to create a Salesforce web service, the following example might be helpful.
global class MyWebService
{
webservice static AggregateResult MyWebServiceMethod()
{
AggregateResult ar = [
SELECT
HOUR_IN_DAY(convertTimezone(CreatedDate)) Hour,
SUM(Amount) Amount
FROM Opportunity
GROUP BY HOUR_IN_DAY(convertTimezone(CreatedDate))];
system.debug(ar);
return ar;
}
}

Related

Is there any way we can parse s string expression in Apache Flink Table API?

I am trying to perform aggregation using Flink Table API by accepting group by field and field aggregation expressions as string parameters from the user.
Input
GroupBy Field = department
aggregation Field Expression = count(employeeId), max(salary)
Is there any way we can do it using flink Table API? I tried to do the following, but it didn't help. Does flink have anything equivalent to selectExpr function in spark?
https://spark.apache.org/docs/3.1.3/api/python/reference/api/pyspark.sql.DataFrame.selectExpr.html
employeeTable
.groupBy($("department"))
.select(
$("department"),
$("count(employeeId)").as("numberOfEmployees"),
$("max(salary)").as("maxSalary")
)
It is throwing the following exception
Exception in thread "main" org.apache.flink.table.api.ValidationException: Cannot resolve field [count(employeeId)], input field list:[department].
No, I don't believe this will work. Flink's SQL planner wants to know what the query is doing at compile time.
What you can do is construct a SQL query and create a new job to run that query. The SQL gateway that's coming in Flink 1.16 (see FLIP-91) should make this easier.
I think you have wrong syntax.
.select(
$("department"),
$("count(employeeId)").as("numberOfEmployees"),
$("max(salary)").as("maxSalary")
)
count and max you should call like this :
$("employeeId").count().as("numberOfEmployees"),
$("salary").max().as("maxSalary")
You can check Built-in functions here

Fetching ElasticSearch Results into SQL Server by calling Web Service using SQL CLR

Code Migration due to Performance Issues :-
SQL Server LIKE Condition ( BEFORE )
SQL Server Full Text Search --> CONTAINS ( BEFORE )
Elastic Search ( CURRENTLY )
Achieved So Far :-
We have a web page created in ASP.Net Core which has a Auto Complete Drop Down of 2.5+ Million Companies Indexed in Elastic Search https://www.99corporates.com/
Due to performance issues we have successfully shifted our code from SQL Server Full Text Search to Elastic Search and using NEST v7.2.1 and Elasticsearch.Net v7.2.1 in our .Net Code.
Still looking for a solution :-
If the user does not select a company from the Auto Complete List and simply enters a few characters and clicks on go then a list should be displayed which we had done earlier by using the SQL Server Full Text Search --> CONTAINS
Can we call the ASP.Net Web Service which we have created using SQL CLR and code like SELECT * FROM dbo.Table WHERE Name IN( dbo.SQLWebRequest('') )
[System.Web.Script.Services.ScriptMethod()]
[System.Web.Services.WebMethod]
public static List<string> SearchCompany(string prefixText, int count)
{
}
Any better or alternate option
While that solution (i.e. the SQL-APIConsumer SQLCLR project) "works", it is not scalable. It also requires setting the database to TRUSTWORTHY ON (a security risk), and loads a few assemblies as UNSAFE, such as Json.NET, which is risky if any of them use static variables for caching, expecting each caller to be isolated / have their own App Domain, because SQLCLR is a single, shared App Domain, hence static variables are shared across all callers, and multiple concurrent threads can cause race-conditions (this is not to say that this is something that is definitely happening since I haven't seen the code, but if you haven't either reviewed the code or conducted testing with multiple concurrent threads to ensure that it doesn't pose a problem, then it's definitely a gamble with regards to stability and ensuring predictable, expected behavior).
To a slight degree I am biased given that I do sell a SQLCLR library, SQL#, in which the Full version contains a stored procedure that also does this but a) handles security properly via signatures (it does not enable TRUSTWORTHY), b) allows for handling scalability, c) does not require any UNSAFE assemblies, and d) handles more scenarios (better header handling, etc). It doesn't handle any JSON, it just returns the web service response and you can unpack that using OPENJSON or something else if you prefer. (yes, there is a Free version of SQL#, but it does not contain INET_GetWebPages).
HOWEVER, I don't think SQLCLR is a good fit for this scenario in the first place. In your first two versions of this project (using LIKE and then CONTAINS) it made sense to send the user input directly into the query. But now that you are using a web service to get a list of matching values from that user input, you are no longer confined to that approach. You can, and should, handle the web service / Elastic Search portion of this separately, in the app layer.
Rather than passing the user input into the query, only to have the query pause to get that list of 0 or more matching values, you should do the following:
Before executing any query, get the list of matching values directly in the app layer.
If no matching values are returned, you can skip the database call entirely as you already have your answer, and respond immediately to the user (much faster response time when no matches return)
If there are matches, then execute the search stored procedure, sending that list of matches as-is via Table-Valued Parameter (TVP) which becomes a table variable in the stored procedure. Use that table variable to INNER JOIN against the table rather than doing an IN list since IN lists do not scale well. Also, be sure to send the TVP values to SQL Server using the IEnumerable<SqlDataRecord> method, not the DataTable approach as that merely wastes CPU / time and memory.
For example code on how to accomplish this correctly, please see my answer to Pass Dictionary to Stored Procedure T-SQL
In C#-style pseudo-code, this would be something along the lines of the following:
List<string> = companies;
companies = SearchCompany(PrefixText, Count);
if (companies.Length == 0)
{
Response.Write("Nope");
}
else
{
using(SqlConnection db = new SqlConnection(connectionString))
{
using(SqlCommand batch = db.CreateCommand())
{
batch.CommandType = CommandType.StoredProcedure;
batch.CommandText = "ProcName";
SqlParameter tvp = new SqlParameter("ParamName", SqlDbType.Structured);
tvp.Value = MethodThatYieldReturnsList(companies);
batch.Paramaters.Add(tvp);
db.Open();
using(SqlDataReader results = db.ExecuteReader())
{
if (results.HasRows)
{
// deal with results
Response.Write(results....);
}
}
}
}
}
Done. Got the solution.
Used SQL CLR https://github.com/geral2/SQL-APIConsumer
exec [dbo].[APICaller_POST]
#URL = 'https://www.-----/SearchCompany'
,#JsonBody = '{"searchText":"GOOG","count":10}'
Let me know if there is any other / better options to achieve this.

Power BI SFDC Object Connection - Task - Navigation Query Error

I am hoping to get some help with the following error when I try to connect to the Task object in Salesforce. It is showing at the Navigation query (Task1 below) and I am unclear as to the nature of the error or resolution.
DataSource.Error: exceeded 100000 distinct who/what's
Details:
List
Query:
let
Source = Salesforce.Data(),
Task1 = Source{[Name="Task"]}[Data]
in
Task1
The task volume in our SFDC instance is excessive, though I have previously been applying a date filter after the Navigation query (Task1 above) which is where I am currently experiencing the error, thus precluding me from using a date filter as I had been with other objects.
Thanks,
Rich
It is a permission problem/limitation. You can find the solution here.

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

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

The Microsoft Access Database Engine does not recognize

I use Access at work, I'm mostly self-taught and I know very little code . I've built a data base for handling HR KPI´S. In some of my queries, since 2016 started (2015 still runs), several reports I run now pops the error:
"The Microsoft Access Database Engine does not recognize 'C_Hrs_Permiso_TI_NT.NOTRAB' as a valid field name or expression".
I'm not sure why the report would be giving me an error about it.
Query Code:
TRANSFORM Sum(Hrs_Permiso_TI_NT.MONTOO) AS SumaDeMONTOO
SELECT Hrs_Permiso_TI_NT.EMPRESA,
Hrs_Permiso_TI_NT.CENCOS,
Left([Hrs_Permiso_TI_NT]![AMES],4) AS Año,
Right([Hrs_Permiso_TI_NT]![AMES],2) AS Mes,
Hrs_Permiso_TI_NT.CODIGO,
Fecha_maxmes_Calendario.MáxDeFecha
FROM Hrs_Permiso_TI_NT INNER JOIN Fecha_maxmes_Calendario
ON Hrs_Permiso_TI_NT.AMES=Fecha_maxmes_Calendario.Ames
GROUP BY Hrs_Permiso_TI_NT.EMPRESA,
Hrs_Permiso_TI_NT.CENCOS,
Left([Hrs_Permiso_TI_NT]![AMES],4),
Right([Hrs_Permiso_TI_NT]![AMES],2),
Hrs_Permiso_TI_NT.CODIGO,
Fecha_maxmes_Calendario.MáxDeFecha
PIVOT Hrs_Permiso_TI_NT.COHADE;
As soon as this query doesn't contain C_Hrs_Permiso_TI_NT, it means that the problem is one of queries 'Hrs_Permiso_TI_NT' or Fecha_maxmes_Calendario. Try to open them and locate error

Resources