How to cross join tables from multiple servers? - sql-server

I'm working on a project to create a table that pull information from my local server and 2 online servers. The 2 online servers are both linked with my local server. I only have ability to read from the online servers and the data is to large for me to create a duplicate.
I built some code that would work on Management Studio, however when I place those code into SSRS, I got message that says one of my table already exists. I tried to put a drop table clause in front of that, but then I got message for the next table down the line already existed. And if I pull drop statement for every table, I got a error message for Timeout expired when refresh the fields.
SELECT s.SiteID, s.[StoreName], cf.CustomerID, , cf.AccountNumber, cf.AccountStatus,
cf.Store_ID, cf.InstitutionID, cf.TransactionTime, cf.Comment
INTO #Report_Table1
FROM dbo.View_GetCustomerInfo cf
LEFT JOIN dbo.Store_Table s ON cf.Store_ID = s.Store_ID
;
SELECT t.*, cl.SaleAmount
INTO #Report_Table2
FROM #Report_Table1 t
LEFT JOIN OnlineServe01.Views.dbo.SaleUpdate su
ON t.CustomerID = cl.CustomerID AND t.Store_ID = cl.Store_ID AND [Status] = 'A'
;
SELECT InstitutionID, Source_ID, BankName
INTO #Report_BankName
FROM OnlineServe01.Views.dbo.InstitutionInfo bn
WHERE InstitutionID IN (
SELECT InstitutionID FROM #Report_Table2)
;
SELECT df.*, bn.BankName
INTO #Report_Table3
FROM #Report_Table2 t
LEFT JOIN #Report_BankName bn ON df.InstitutionID = bn.InstitutionID AND df.Store_ID = bn.Store_ID
;
SELECT StoreName, SiteID, CustomerID, SaleAmount
, BankName, AccountNumber, AccountStatus, TransactionTime, Comment
INTO #Report_Table4
FROM #Report_Table3 t
;
SELECT *
INTO #Report_PlayerName
FROM (
SELECT DISTINCT CustomerID, FirstName, LastName,
Dense_Rank () OVER (Partition by CustomerID ORDER BY FirstName) AS Rnk
FROM OnlineServe02.CustomerManagement.dbo.CustomerName
WHERE PreferredName = 0
AND CustomerID IN (SELECT DISTINCT CustomerID FROM #Report_Table4)
) a
WHERE Rnk = 1
;
SELECT t.*, pn.LastName, pn.FirstName, ca.Deposited, ca.Used, ca.InTransit, ca.Available
FROM #Report_Table4 t
LEFT JOIN OnlineServe02.CustomerManagement.dbo.AccountActivity ca
ON t.CustomerID = ca.CustomerID AND t.SiteID = ca.SiteID
LEFT JOIN #Report_PlayerName pn ON t.CustomerID = pn.CustomerID
;

Related

T-Sql How to get Max dated records?

I want max dated rows for per GroupCode
I wrote this.
SELECT FH.BelgeNo AS FaturaNo
,FHD.UrunId
,FH.Tarih
,UG.Grup AS GrupKodu
,FHD.Kodu
,FHD.UrunAdi
,FHD.BirimFiyat
FROM FirmaHareketDetayi FHD
LEFT JOIN FirmaHareketleri FH ON FH.ID = FHD.HareketId
LEFT JOIN Urunler U ON U.UrunId = FHD.UrunId --and U.Kodu = FHD.Kodu
LEFT JOIN UrunGruplari UG ON UG.GrupId = U.GrupId
WHERE FHD.Kodu = '2S619H307CF'
AND FH.FirmaId = 2610
ORDER BY Tarih DESC
and results are like this
There are 2 PIERBURG rows.
is it possible to get only one PIERBURG ?
I mean max dated one (Tarih: Date column, GrupKodu: Group Code)
Notes: Table UrunGrupları: ProductGroups
Table FirmaHareketleri: FirmMovements
Table FirmaHareketDetayi: FirmMovementDetails (Connected with FirmMovements by HareketId (Foreign Key))
Sorry about my english :(
You can use window functions for this
;with cte as (
SELECT FH.BelgeNo AS FaturaNo
,FHD.UrunId
,FH.Tarih
,UG.Grup AS GrupKodu
,FHD.Kodu
,FHD.UrunAdi
,FHD.BirimFiyat
, row_number() over(partition by UG.Grup order by FH.Tarih desc) as rownum
FROM FirmaHareketDetayi FHD
LEFT JOIN FirmaHareketleri FH ON FH.ID = FHD.HareketId
LEFT JOIN Urunler U ON U.UrunId = FHD.UrunId --and U.Kodu = FHD.Kodu
LEFT JOIN UrunGruplari UG ON UG.GrupId = U.GrupId
WHERE FHD.Kodu = '2S619H307CF'
AND FH.FirmaId = 2610
)
select *
from cte
where rownum = 1

Update records SQL?

First when I started this project seemed very simple. Two tables, field tbl1_USERMASTERID in Table 1 should be update from field tbl2_USERMASTERID Table 2. After I looked deeply in Table 2, there is no unique ID that I can use as a key to join these two tables. Only way to match the records from Table 1 and Table 2 is based on FIRST_NAME, LAST_NAME AND DOB. So I have to find records in Table 1 where:
tbl1_FIRST_NAME equals tbl2_FIRST_NAME
AND
tbl1_LAST_NAME equals tbl2_LAST_NAME
AND
tbl1_DOB equals tbl2_DOB
and then update USERMASTERID field. I was afraid that this can cause some duplicates and some users will end up with USERMASTERID that does not belong to them. So if I find more than one record based on first,last name and dob those records would not be updated. I would like just to skip and leave them blank. That way I wouldn't populate invalid USERMASTERID. I'm not sure what is the best way to approach this problem, should I use SQL or ColdFusion (my server side language)? Also how to detect more than one matching record?
Here is what I have so far:
UPDATE Table1 AS tbl1
LEFT OUTER JOIN Table2 AS tbl2
ON tbl1.dob = tbl2.dob
AND tbl1.fname = tbl2.fname
AND tbl1.lname = tbl2.lname
SET tbl1.usermasterid = tbl2.usermasterid
WHERE LTRIM(RTRIM(tbl1.usermasterid)) = ''
Here is query where I tried to detect duplicates:
SELECT DISTINCT
tbl1.FName,
tbl1.LName,
tbl1.dob,
COUNT(*) AS count
FROM Table1 AS tbl1
LEFT OUTER JOIN Table2 AS tbl2
ON tbl1.dob = tbl2.dob
AND tbl1.FName = tbl2.first
AND tbl1.LName = tbl2.last
WHERE LTRIM(RTRIM(tbl1.usermasterid)) = ''
AND LTRIM(RTRIM(tbl1.first)) <> ''
AND LTRIM(RTRIM(tbl1.last)) <> ''
AND LTRIM(RTRIM(tbl1.dob)) <> ''
GROUP BY tbl1.FName,tbl1.LName,tbl1.dob
Some data after I tested query above:
First Last DOB Count
John Cook 2008-07-11 2
Kate Witt 2013-06-05 1
Deb Ruis 2016-01-22 1
Mike Bennet 2007-01-15 1
Kristy Cruz 1997-10-20 1
Colin Jones 2011-10-13 1
Kevin Smith 2010-02-24 1
Corey Bruce 2008-04-11 1
Shawn Maiers 2016-08-28 1
Alenn Fitchner 1998-05-17 1
If anyone have idea how I can prevent/skip updating duplicate records or how to improve this query please let me know. Thank you.
You could check for and avoid duplicate matches using with common_table_expression (Transact-SQL)
along with row_number()., like so:
with cte as (
select
t.fname
, t.lname
, t.dob
, t.usermasterid
, NewUserMasterId = t2.usermasterid
, rn = row_number() over (partition by t.fname, t.lname, t.dob order by t2.usermasterid)
from table1 as t
inner join table2 as t2 on t.dob = t2.dob
and t.fname = t2.fname
and t.lname = t2.lname
and ltrim(rtrim(t.usermasterid)) = ''
)
--/* confirm these are the rows you want updated
select *
from cte as t
where t.NewUserMasterId != ''
and not exists (
select 1
from cte as i
where t.dob = i.dob
and t.fname = i.fname
and t.lname = i.lname
and i.rn>1
);
--*/
/* update those where only 1 usermasterid matches this record
update t
set t.usermasterid = t.NewUserMasterId
from cte as t
where t.NewUserMasterId != ''
and not exists (
select 1
from cte as i
where t.dob = i.dob
and t.fname = i.fname
and t.lname = i.lname
and i.rn>1
);
--*/
I use the cte to extract out the sub query for readability. Per the documentation, a common table expression (cte):
Specifies a temporary named result set, known as a common table expression (CTE). This is derived from a simple query and defined within the execution scope of a single SELECT, INSERT, UPDATE, or DELETE statement.
Using row_number() to assign a number for each row, starting at 1 for each partition of t.fname, t.lname, t.dob. Having those numbered allows us to check for the existence of duplicates with the not exists() clause with ... and i.rn>1
You could use a CTE to filter out the duplicates from Table1 before joining:
; with CTE as (select *
, count(ID) over (partition by LastName, FirstName, DoB) as IDs
from Table1)
update a
set a.ID = b.ID
from Table2 a
left join CTE b
on a.FirstName = b.FirstName
and a.LastName = b.LastName
and a.Dob = b.Dob
and b.IDs = 1
This will work provided there are no exact duplicates (same demographics and same ID) in table 1. If there are exact duplicates, they will also be excluded from the join, but you can filter them out before the CTE to avoid this.
Please try below SQL:
UPDATE Table1 AS tbl1
INNER JOIN Table2 AS tbl2
ON tbl1.dob = tbl2.dob
AND tbl1.fname = tbl2.fname
AND tbl1.lname = tbl2.lname
LEFT JOIN Table2 AS tbl3
ON tbl3.dob = tbl2.dob
AND tbl3.fname = tbl2.fname
AND tbl3.lname = tbl2.lname
AND tbl3.usermasterid <> tbl2.usermasterid
SET tbl1.usermasterid = tbl2.usermasterid
WHERE LTRIM(RTRIM(tbl1.usermasterid)) = ''
AND tbl3.usermasterid is null

Excluding certain results of the query SQL Server

I have 3 tables: CLIENT, FEATURE, CLIENT_FEATURE
Table CLIENT: id_client, name, surname, address
Table FEATURE: id_feature, feature_txt
Table FEATURE_CLIENT: id_fc, fc_id_client, fc_id_feature
One client can have multiple features.
If I want to see clients with desired 1 feature:
SELECT
[id_client], [name], [surname], [address], [id_feature],
[feature_txt], [id_fc], [fc_id_client], [fc_id_feature]
FROM
[client]
LEFT JOIN
[feature] ON fc_id_client = id_client
WHERE
fc_id_feature = 1
It is ok, but If the client has the feature 1 and 20 and I want to search for clients without feature 20
I tested:
SELECT
[id_client], [name], [surname], [address],[id_feature],
[feature_txt], [id_fc], [fc_id_client], [fc_id_feature]
FROM
[client]
LEFT JOIN
[feature] ON fc_id_client = id_client AND fc_id_client <> 20
WHERE
fc_id_client = 1
but it is not working.
SELECT *
FROM
[client]
INNER JOIN
[feature_client] ON
client.id_client = feature_client.fc_id_client
INNER JOIN
[feature] ON
feature_client.fc_id_feature = feature.id_feature
WHERE
fc_id_feature = 1 AND
id_client NOT IN
(
SELECT fc_id_client
FROM
feature_client
INNER JOIN
feature ON
fc_id = id_feature
WHERE id_feature = 8
)

SQL - How to only show the row with the greatest date value based on ID?

I have SQL statements in SQL Server 2008 R2 based on a few joined tables that utilizes all the information I need in my program:
SELECT
Laptops.Laptop_ID,
Laptops.Model_Name,
...
Users.Firstname + Users.Lastname AS Name,
Loans.Date_Loaned
FROM Users
INNER JOIN Loans ON Users.User_ID = Loans.User_ID
RIGHT OUTER JOIN Laptops ON Loans.Laptop_ID = Laptops.Laptop_ID
This brings up a table similar to:
ID Model_Name ... Name Date_Loaned
1 ... ... Kris 18-08-11
2 ... ... Jo 20-08-11
2 ... ... Bert 18-08-11
4 ... ... Sam 19-08-11
What I'm trying to do is where there would be repeated ID, I want to only show the row with the highest date, like this:
ID Model_Name ... Name Date_Loaned
1 ... ... Kris 18-08-11
2 ... ... Jo 20-08-11
4 ... ... Sam 19-08-11
I'm having problems figuring out how to do this with the SQL statement that I already have. Help!
Use windows functions:
SELECT * FROM(
SELECT Laptops.Laptop_ID,
Laptops.Model_Name,
...
Users.Firstname + Users.Lastname AS Name,
Loans.Date_Loaned,
row_number()
over(partition by Laptops.Laptop_ID
order by Loans.Date_Loaned desc) rn
FROM Users
INNER JOIN Loans ON Users.User_ID = Loans.User_ID
RIGHT OUTER JOIN Laptops ON Loans.Laptop_ID = Laptops.Laptop_ID) t
WHERE rn = 1
Try this
SELECT Laptops.Laptop_ID,
Laptops.Model_Name,
...
Users.Firstname + Users.Lastname AS Name,
MAX(Loans.Date_Loaned) AS date
FROM Users
INNER JOIN Loans ON Users.User_ID = Loans.User_ID
RIGHT OUTER JOIN Laptops ON Loans.Laptop_ID = Laptops.Laptop_ID
GROUP BY Laptops.Laptop_ID,
Laptops.Model_Name,
...
Users.Firstname + Users.Lastname AS Name
Glad you got your answer, but just wanted to mention you might get better performance selecting from Laptops and LEFT OUTER JOIN your Users/Loans sub query. It might be a little easier for the next person to decipher since RIGHT OUT JOIN is not used very often. Using aliases also helps eliminate some typing.
SELECT
l.Laptop_ID,
l.Model_Name,
ul.Name,
ul.Date_Loaned
FROM
Laptops l
LEFT JOIN (
SELECT l.Laptop_ID,
u.Firstname + u.Lastname AS Name,
l.Date_Loaned,
ROW_NUMBER() OVER(PARTITION BY l.Laptop_ID ORDER BY l.Date_Loaned desc) Rn
FROM Loans l
JOIN Users u ON l.User_ID = u.User_ID
) ul ON l.Laptop_ID = ul.Laptop_ID
AND ul.Rn = 1

Select 1 of 2 similar records where does not

So I have a table called 'Requests' which stores requests for holidays. I want to try extract certain records from the table (joined with others) with the parameter of the clocknumber. But, if there are two records with the same HolidayID and the last (top 1 desc) is of a certain value - we dont include that in the select!
Request Table [shortened down version of it];
http://i.stack.imgur.com/YY1Gk.png
The stored procedure im using is passed a parameter for the username and joins three other tables,
a 'Holidays' table (Stores information on the holiday from, to etc)
a 'Users' table (contains usernames etc)
a 'RequestType' table (contains the types of requests)
From the image of the table, If you imagine all of those requests belong to the same user, I would want to extract only the records with a requesttype of 1. (the requesttype 1 is holiday request and 2 is holiday cancel). But, if there is a second record with the same holidayID and a requesttype of 2, it does not include that.
So running the query, I would want to only get records with the ID 1 and 2, because the last 2 have the same Holiday ID, and the last of the 2 is with a requesttype to cancel the holiday.
Here is my attempted query;
SELECT Holidays.ID, EmployeeClockNumber, Employees.Name AS EmployeeName, HolidayStart, HolidayEnd, HalfDay, AMPM
FROM Holidays
INNER JOIN Employees ON Employees.ClockNumber = Holidays.EmployeeClockNumber
INNER JOIN Requests ON Requests.HolidayID = Holidays.ID
WHERE EmployeeClockNumber = #ClockNo
AND Requests.Accepted = 1
AND RequestTypeID = (SELECT TOP 1 Requests.ID
FROM Requests
INNER JOIN Holidays ON Holidays.ID = Requests.HolidayID
WHERE Requests.RequestTypeID = (SELECT ID FROM RequestType WHERE RequestType = 'Holiday Request')
AND Holidays.EmployeeClockNumber = #ClockNo
ORDER BY Requests.ID DESC)
ORDER BY ID DESC
Could someone point me in the right direction? Thank you
edit: ive got it working myself!
SELECT Holidays.ID, Holidays.EmployeeClockNumber, Employees.Name AS EmployeeName, Holidays.HolidayStart, Holidays.HolidayEnd, Holidays.HalfDay, Holidays.AMPM
FROM Requests
INNER JOIN Holidays ON Holidays.ID = Requests.HolidayID
INNER JOIN Employees ON Employees.ClockNumber = Holidays.EmployeeClockNumber
WHERE Holidays.EmployeeClockNumber = #ClockNo
AND Requests.Accepted = 1
AND Requests.HolidayID NOT IN (SELECT TOP 1 HolidayID
FROM Requests AS R1
WHERE R1.RequestTypeID <> (SELECT ID FROM RequestType WHERE RequestType = 'Holiday Request')
AND R1.HolidayID = Requests.HolidayID
ORDER BY R1.ID DESC)
SELECT * FROM TAB WHERE requestTypeID = 1
AND holidayID not in (SELECT HolidayID from TAB WHERE requestTypeID = 2)
I would use a partition on the select and then filter on that.
So something like
DECLARE #mtable TABLE (
ID INT
,RequestTypeId INT
,HolidayId INT
,Accepted NVARCHAR(50)
)
INSERT #mtable VALUES (1,1,1,'True')
INSERT #mtable VALUES (2,1,2,'True')
INSERT #mtable VALUES (3,1,3,'True')
INSERT #mtable VALUES (4,2,3,'True')
SELECT * FROM (
SELECT MAX(RequestTypeId) OVER (PARTITION BY HolidayID) AS MaxType
,Id
FROM #mtable
) q
WHERE q.MaxType <> 2

Resources