SQL Server to SalesForce Linked Server Nightmare - sql-server

I am getting inconsistent results from joining Linked Servers. It's something that should be relatively simple... but has taken me hours to get this figured out. I am using SQL Server 2014 and the CData ODBC Driver to Join to SalesForce. I'm not doing anything fancy just trying to perform standard CRUD operations but again and again it seems that when ever I filter these linked server tables that sometimes results do not produce.
My current and main issue right now is I am having difficulty JOINING two Linked tables to two Local tables. If I remove one of the Linked tables from the join results are produced. But whenever I add two linked tables to the joins it produces and empty record set.
And yes all the related identifiers exist so it really is an issue with the Linked Server. Here are the three variations that I've tried:
SELECT * FROM Offer_Interest oi
INNER JOIN Offer o ON oi.Offer_ID_SQL = o.Offer_ID_SQL
INNER JOIN OPENQUERY([TR-SF-PROD], 'SELECT Id, OFFER_ID_SQL__C FROM Offer__c') osf ON o.Offer_ID_SQL =osf.OFFER_ID_SQL__C
INNER JOIN Interest i ON oi.Interest_ID_SQL = i.Interest_ID_SQL
INNER JOIN OPENQUERY([TR-SF-PROD], 'SELECT INTEREST_ID_SQL__C, Id FROM Interest__c') isf ON i.Interest_ID_SQL =isf.Interest_ID_SQL__c
WHERE o.PrimaryContact_ID_SQL = 2803
I've also tried without OPENQUERY:
SELECT * FROM FROM Offer_Interest oi
INNER JOIN Offer o ON oi.Offer_ID_SQL = o.Offer_ID_SQL
INNER JOIN [TR-SF-PROD].[CDataSalesforce].[Salesforce].[Offer__c] osf ON o.Offer_ID_SQL =osf.OFFER_ID_SQL__C
INNER JOIN Interest i ON oi.Interest_ID_SQL = i.Interest_ID_SQL
INNER JOIN [TR-SF-PROD].[CDataSalesforce].[Salesforce].[Interest__c] isf ON i.Interest_ID_SQL =isf.Interest_ID_SQL__c
WHERE o.PrimaryContact_ID_SQL = 2803
And Lastly I've also created Synonyms to the Linked Server tables. All of these work using the same filter or WHERE CLAUSE if I run them seperately although the linked server tables seem buggy if I filter them without OPENQUERY.
This is my first experience Linking a Server to SQL Server so anyone with experience in this or what the issue may be would be greatly appreciated!

Not the answer I was hoping as it should just work. But a temp fix I came up with is stuffing the linked server values I need into Temp Tables then joining on the temp tables, which worked... but of course this adds time onto the execution of the overall stored procedure so it is definitely not the ideal solution. If anyone has a better idea please still answer!!
IF EXISTS(SELECT [NAME] FROM tempdb.sys.tables WHERE [NAME] like '#TempOffer%') BEGIN
DROP TABLE #TempOffer;
END;
SELECT * INTO #TempOffer FROM OPENQUERY([TR-SF-PROD], 'SELECT Id, OFFER_ID_SQL__C FROM Offer__c')
IF EXISTS(SELECT [NAME] FROM tempdb.sys.tables WHERE [NAME] like '#TempInterest%') BEGIN
DROP TABLE #TempInterest;
END;
SELECT * INTO #TempInterest FROM OPENQUERY([TR-SF-PROD], 'SELECT INTEREST_ID_SQL__C, Id FROM Interest__c')
SELECT * FROM Offer_Interest oi
INNER JOIN Offer o ON oi.Offer_ID_SQL = o.Offer_ID_SQL
INNER JOIN #TempOffer osf ON o.Offer_ID_SQL =osf.OFFER_ID_SQL__C
INNER JOIN Interest i ON oi.Interest_ID_SQL = i.Interest_ID_SQL
INNER JOIN #TempInterest isf ON i.Interest_ID_SQL =isf.Interest_ID_SQL__c
WHERE o.PrimaryContact_ID_SQL = 2803

Related

Create stored procedure and write a query for joining multi table based on columns in SQL Server

I am beginner to SQL, this is my first exercise to create a stored procedure​ in SQL. I need to get all the rows of all the persons with columns FirstName, MiddleName, LastName, email address, phone number and phonenumber type.
I have to join (required to use join) these 4 tables Person.person, person.personphone, person.phonenumbertype, person.emailaddress and retrieve the columns mentioned above.
The data I am using is the AdventureWorks 2016 SQL Server sample database, which has around 20k rows.
I tried inner joining on two tables to start with and the execution seems never ending.
select FirstName as firstname
from Person.Person
inner join person.EmailAddress on Person.Person.BusinessEntityID = Person.EmailAddress.BusinessEntityID
Thanks allmhuran and marc_s for the corrections.
Advice any link or suggestions on how I can get solution to this query.
You need something like this:
-- select the columns you want
SELECT
p.FirstName, p.MiddleName, p.LastName,
pe.EmailAddress, pp.PhoneNumber, pnt.Name AS PhoneNumberType
FROM
-- this is your "base" table - where most of the info exists
Person.Person p
INNER JOIN
-- join to the e-mail table - based on "BusinessEntityID", to get e-mail address
Person.EmailAddress pe ON pe.BusinessEntityID = p.BusinessEntityID
INNER JOIN
-- join to the person phone table - based again on "BusinessEntityID", to get phone number
Person.PersonPhone pp ON pp.BusinessEntityID = p.BusinessEntityID
INNER JOIN
-- join the PersonPhone table to the PhoneNumberType table, to get the type of phone
Person.PhoneNumberType pnt ON pnt.PhoneNumberTypeID = pp.PhoneNumberTypeID
You should always use proper / meaningful aliases for your tables - this makes your list of columns being selected, and your JOIN conditions, just so much more readable!

How can I get 3 tables INNER JOIN in MS SQL Server

From the specialist table, retrieve the first name, last name and contact number for the people that provide care to penguins from the species table.
There are 3 tables: tbl_specialist, tbl_species, tbl_care
I need help trying to INNER JOIN the tables to display First, Last, And Contact for penguins.
SELECT specialist_fname, specialist_lname, specialist_contact
FROM ((tbl_specialist
INNER JOIN tbl_species ON species_care = tbl_species.species_care)
INNER JOIN tbl_care ON care_id = tbl_care.care_id)
WHERE species_name = 'penguin'
;
It's a bit difficult without seeing the exact schema of the tables, but your syntax for the subquery is a bit off and you need to alias columns that are found in multiple tables in a JOIN statment. Try rewriting your SQL like this:
SELECT spl.specialist_fname, spl.specialist_lname, spl.specialist_contact
FROM tbl_specialist spl
INNER JOIN tbl_species s
ON spl.species_care = s.species_care
INNER JOIN tbl_care c
ON s.care_id = c.care_id
WHERE s.species_name = 'penguin'
I'm obviously inferring which tables certain columns come from in the join, but hopefully you get the idea.
I figured it out thank you.
SELECT specialist_fname, specialist_lname, specialist_contact
FROM ((tbl_specialist
INNER JOIN tbl_care ON tbl_care.care_specialist = tbl_specialist.specialist_id)
INNER JOIN tbl_species ON tbl_species.species_care= tbl_care.care_id)
WHERE species_name = 'penguin'
;

TSQL - Return all record ids and the missing id's we need to populate

I have a job I need to automate to make sure a cache for some entities in my database is populated. I have the query below using CTE and CROSS JOIN but it doesn't run very quickly so I'm sure it can be improved.
The issue:
I have a database of employees
Each employee has a report of data compiled each month.
Each report has a set of 'components' and each of those components 'data' is pulled from an external source and cached in my database
The goal:
I want to set up a job to take a group of component Ids for 'this months report' and pre-cache the data if it doesn't exist.
I need to get a list of employees and the components they are missing in the cache for this months report. I will then set up a CRON job to process the queue.
The Question
My query below is slow - Is there a more efficient way to return a list of employees and the component ids that are missing in the cache?
The current SQL:
declare #reportDate datetime2 = '2019-10-01'; //the report publish date
declare #componentIds table (id int); // store the ids of each cachable component
insert #componentIds(id) values(1),(2),(3),(4),(5);
;WITH cteCounts
AS (SELECT r.Id as reportId, cs.componentId,
COUNT(1) AS ComponentCount
FROM EmployeeReports r
LEFT OUTER JOIN CacheStore cs on r.Id = cs.reportId and cs.componentId in (SELECT id FROM #componentIds)
GROUP BY r.Id, cs.componentId)
SELECT e.Id, e.name, _c.id as componentId, r.Id as reportId
FROM Employees e
INNER JOIN EmployeeReports r on e.Id = r.employeeId and r.reportDate = #reportDate
CROSS JOIN #componentIds _c
LEFT OUTER JOIN cteCounts AS cn
ON _c.Id = cn.componentId AND r.Id = cn.reportId
WHERE cn.ComponentCount is null
2 things I can suggest doing:
Use NOT EXISTS instead of a LEFT JOIN + IS NULL. The execution plan is prone to be different when you tell the engine that you want records that don't have any occurrence in a particular set Vs. joining and making sure that the joined column is null.
SELECT e.Id, e.name, _c.id as componentId, r.Id as reportId
FROM Employees e
INNER JOIN EmployeeReports r on e.Id = r.employeeId and r.reportDate = #reportDate
CROSS JOIN #componentIds _c
WHERE
NOT EXISTS (SELECT 'no record' FROM cteCounts AS cn
WHERE _c.Id = cn.componentId AND r.Id = cn.reportId)
Use temporary tables instead of CTE and/or variable tables. If you have to handle many rows, variable tables don't actually have statistics on and some complex CTE's might actually make lousy execution plans. Try using temporary tables instead of these 2 and see if the performance boosts. Also try creating relevant indexes on them if your row count is high.

Inner join + set max date + naming in ACCESS SQL

I am migrating a query from tables held in MS SQL Server to MS Access 2016. I can't seem to figure out how to use the very common max_date inner join from my SQL query and import to my Access query.
I have searched the site and seen many explanations for how to do it in SQL, and my query in SQL works just fine. My Access query will not work.
INNER JOIN (
SELECT dbo_LTS_TRANSACTION_HISTORY.[RFIDTAGID], max(dbo_LTS_TRANSACTION_HISTORY.[TRANSCATION_DATE]) as [max_trxn_date]
FROM dbo_LTS_TRANSACTION_HISTORY
GROUP BY dbo_LTS_TRANSACTION_HISTORY.[RFIDTAGID]) as b
ON dbo_LTS_TRANSACTION_HISTORY.[RFIDTAGID] = b.[RFIDTAGID] AND (dbo_LTS_TRANSACTION_HISTORY.[TRANSCATION_DATE] = b.[max_trxn_date]))
I expect my [TRANSCATION_DATE] to only hold the [max_trxn_date] so only one max date record is pulled for each [RFIDTAGID]. Without naming the join "as b" I don't know how to make this work. Access doesn't seem to take the naming structure I'm used to in SQL. I am getting a compile error for syntax.
Full code below
SELECT dbo_LTS_TRANSACTION_HISTORY.PROD_ORDER, dbo_LTS_TRANSACTION_HISTORY.PART_NUMBER, dbo_LTS_PACKAGE.QUANTITY, dbo_LTS_TRANSACTION_HISTORY.LOCATION, dbo_LTS_TRANSACTION_HISTORY.TRANSCATION_DATE, dbo_LTS_TRANSACTION_HISTORY.CONTAINER_RFIDTAGID, dbo_LTS_TRANSACTION_HISTORY.RFIDTAGID, dbo_LTS_DISCRETE_JOB_SUMMARY.MFG_DELIVERY_DATE, dbo_LTS_DISCRETE_JOB_SUMMARY.EXTENSION_DATE, dbo_LTS_DISCRETE_JOB_SUMMARY.STATUS, dbo_LTS_DISCRETE_JOB_SUMMARY.PBG, dbo_LTS_LOCATION.TYPE
FROM (dbo_LTS_LOCATION
INNER JOIN (dbo_LTS_DISCRETE_JOB_SUMMARY
INNER JOIN dbo_LTS_TRANSACTION_HISTORY
ON (dbo_LTS_DISCRETE_JOB_SUMMARY.[PROD_ORDER] = dbo_LTS_TRANSACTION_HISTORY.[PROD_ORDER])
AND (dbo_LTS_DISCRETE_JOB_SUMMARY.[DISCRETE_JOB_NUMBER] = dbo_LTS_TRANSACTION_HISTORY.[JOB_NUMBER]))
ON dbo_LTS_LOCATION.[DESIGNATION] = dbo_LTS_TRANSACTION_HISTORY.[LOCATION])
INNER JOIN dbo_LTS_PACKAGE ON dbo_LTS_TRANSACTION_HISTORY.[RFIDTAGID] = dbo_LTS_PACKAGE.[RFIDTAGID]
INNER JOIN (
SELECT dbo_LTS_TRANSACTION_HISTORY.[RFIDTAGID], max(dbo_LTS_TRANSACTION_HISTORY.[TRANSCATION_DATE]) as [max_trxn_date]
FROM dbo_LTS_TRANSACTION_HISTORY
GROUP BY dbo_LTS_TRANSACTION_HISTORY.[RFIDTAGID]) as b
ON dbo_LTS_TRANSACTION_HISTORY.[RFIDTAGID] = b.[RFIDTAGID] AND (dbo_LTS_TRANSACTION_HISTORY.[TRANSCATION_DATE] = b.[max_trxn_date]))
WHERE (((dbo_LTS_TRANSACTION_HISTORY.PROD_ORDER)="123456"));

Query to find Table objects dependent on a Table in SQL Server 2008

I searched online to find a solution to the aforementioned topic but failed to get something that works for me. I only want a SQL statement that will query a database and bring out tables that are dependent on a particular table. I tried the sp_depends approach but it only brought out stored procedures and check constraints in the result set but no tables.
I stumbled on sys.sql_expression_dependenciesbut I discovered it doesn't work for SQL Server 2008. Please I need some help to get this done.
Many thanks.
Simply we can do this In SQL server management studio Right-click on a table and choose 'View Dependencies'.
By using query
Select
S.[name] as 'Dependent_Tables'
From
sys.objects S inner join sys.sysreferences R
on S.object_id = R.rkeyid
Where
S.[type] = 'U' AND
R.fkeyid = OBJECT_ID('tablename')
Another method
SELECT DISTINCT name, so.type
FROM sys.objects AS so
INNER JOIN sys.sql_expression_dependencies AS sed
ON so.object_id = sed.referencing_id
WHERE sed.referenced_id = OBJECT_ID('[tablename]');
Second method selects Procedures, views too.
I found a way around it and I give the credit to Arunprasanth KV for giving a response that guided me to the solution. After studying the schema of the tables properly, the following query gave me exactly what I wanted:
Select
S.[name]
From
sys.objects S inner join sys.sysreferences R
on S.object_id = R.fkeyid
Where
S.[type] = 'U' AND
R.rkeyid = OBJECT_ID('TableName')
GO
Use dm_sql_referencing_entities system view which will give you objects dependent on the table
SELECT referencing_schema_name,
referencing_entity_name,
referencing_id,
referencing_class_desc
FROM sys.Dm_sql_referencing_entities ('schema.Tablename', 'OBJECT')

Resources