Looking up values in multiple tables with multiple joins - sql-server

How would you do a Select statement to lookup a value in a table and then use that value to lookup another value in another table which is then used to lookup a third value in a third table? I cannot do a join from my initial table as there is no common matching field to do the join on.
In my initial table I have an Instr_Id value which is the only possible way to eventually get the Legal_Id value but the table where the Legal_Id is stored does not have an Instr_Id value. In order to do this I need to look up multiple values from 2 other tables to eventually get to the INSTR_ID value.
Example:
I use INSTR_ID in tbl.ABC and join to INSTR_ID in tbl.DEF in order to get the Fin_Enty_Name value in tbl.DEF I then need to use this Fin_Enty_Name value to join to tbl.GHI to get the Fin_Enty_Id . I finally then need to use this Fin_Enty_Id to look up the LEGAL_ID in tbl.JKL so that I can show the LEGAL_ID for each INSTR_ID in my Select query results.
select
a.INSTR_ID,
d.LEGAL_IT
from tbl.ABC as A
Inner join tbl.DEF as B on A.INSTR_ID = B.INSTR_ID

It looks pretty much straight forward:
select a.instr_id, d.legal_id
from tbl.abc a
join tbl.def b
on a.instr_id = b.instr_id
join tbl.ghi c
on b.fin_enty_name = c.fin_enty_name
join tbl.jkl d
on c.fin_enty_id = d.fin_enty_id

Related

How to join two tables in SQL Server, where the IDs are not the same?

I have 2 tables in MS SQL and I am using MS Studio. The first table is called register it has a list of fields. The second table is called Plan and it has a list of fields.
The unique key in the table register is called RegisterID
The unique key in the table Plan is called RegisterID
The goal is to link with a left join the Register to the Plan. My difficulty is that the IDs are not exactly the same: An ID in Plan is xxxx (xxxx being the value of the ID). An ID in Register is xxxx_0 (xxxx being the same value than Plan was added _0)
What is the solution to link those 2 tables in a simple query with fields of both tables?
Here is some more information.
You will find the 2 tables and the expect result of the query.
Tables structure
Expected result
Please note that I am a beginner.
Add the characters to the first field or remove them from the second
select *
from register
left outer join plan on register.RegisterID+'_0' = plan.RegisterID
select *
from register
left outer join plan on register.RegisterID = REPLACE(plan.RegisterID,'_0','')
If the length of the ID is always the same there is a third option
select *
from register
left outer join plan on register.RegisterID = LEFT(plan.RegisterID,6)
You could try something like:
SELECT *
FROM Register R
LEFT OUTER JOIN [Plan] P
ON LEFT(R.RegisterID, LEN(R.RegisterID) - 2) = P.RegisterID
The expression LEFT(R.RegisterID, LEN(R.RegisterID) - 2) will remove the '_0' from Register.RegisterID and the JOIN will work.

Use of scalar functions in Join condition

I am joining with a table to retrieve a value but in order to join I need to do some logic because both the tables do not have a common value in place. So the logic is to do a top 1 and get a certain value from a common table for both the inputs. I am planning to put the logic inside a scalar function and then call it in the join condition.
I have a simple join as something like this
LEFT JOIN <IndexTable> Tbl1 ON Tbl1.PrimaryKey = MainTbl.PrimaryKey
I intend to change this into something like this using a user defined scalar function
LEFT JOIN <IndexTable> Tbl1
ON dbo.fnGetCommonID(Tbl1.PrimaryKey) = dbo.fnGetCommonID(MainTbl.PrimaryKey)
In terms of performance is it good to use it this way or is there any better way for this.
If possible, do your calculation inside the query, maybe using an OUTER APPLY instead of a LEFT JOIN:
OUTER APPLY (
SELECT TOP 1 <at least one field, also values from MainTbl may be used>
FROM <the set of data you need>
WHERE <boolean, also values from MainTbl may be used>
ORDER BY <make the top record the one you want>
) AS Tbl1

left join not showing null values

I need to find the items that exist in table A but not in table B. Now that would be really simple in MySQL doing a join like this
select * from A
left join B on A.key=B.key
where B.key is null
However for some reason this is not working in MSSQL. I have created the query without the where clause to see all the results and I only see matches, not null values. Do you have any idea why this is not working?
I know I can alternatively use "when not exists" but I want to know the reason as to why with a join is not working.
I am adding the code for your review
select Absences.CustomerID, b.*
from (
select * from openquery(JUAN_INTERFACE,'select cmp_wwn from Planet_Customers where i_outcome =4')) b
left join Absences on Absences.CustomerID = b.cmp_wwn
where Absences.Type = 3223
Your where clause is filtering out null values:
where Absences.Type = 3223
You are left-joining from the openquery subquery to Absences; and then filtering only rows that have a specific (non-null) value in an Absences column.
Did you mean to join the other way around, from Absenses to openquery?

SQL Same Column in one row

I have a lookup table that has a Name and an ID in it. Example:
ID NAME
-----------------------------------------------------------
5499EFC9-925C-4856-A8DC-ACDBB9D0035E CANCELLED
D1E31B18-1A98-4E1A-90DA-E6A3684AD5B0 31PR
The first record indicates and order status. The next indicates a service type.
In a query from an orders table I do the following:
INNER JOIN order.id = lut.Statusid
This returns the 'cancelled' name from my lookup table. I also need the service type in the same row. This is connected in the order table by the orders.serviceid How would I go about doing this?
It Cancelled doesnt connect to 31PR.
Orders connects to both. Orders has 2 fields in it called Servicetypeid and orderstatusid. That is how those 2 connect to the order. I need to return both names in the same order row.
I think many will tell you that having two different pieces of data in the same column violates first normal form. There is a reason why having one lookup table to rule them all is a bad idea. However, you can do something like the following:
Select ..
From order
Join lut
On lut.Id = order.StatusId
Left Join lut As l2
On l2.id = order.ServiceTypeId
If order.ServiceTypeId (or whatever the column is named) is not nullable, then you can use a Join (inner join) instead.
A lot of info left out, but here it goes:
SELECT orders.id, lut1.Name AS OrderStatus, lut2.Name AS ServiceType
FROM orders
INNER JOIN lut lut1 ON order.id = lut.Statusid
INNER JOIN lut lut2 ON order.serviceid = lut.Statusid

Iterating 1 row at a time with massive amounts of links/joins

Ok, basically what is needed is a way to have row numbers while using a lot of joins and having where clauses using these rownumbers.
such as something like
select ADDRESS.ADDRESS FROM ADDRESS
INNER JOIN WORKHISTORY ON WORKHISTORY.ADDRESSRID=ADDRESS.ADDRESSRID
INNER JOIN PERSON ON PERSON.PERSONRID=WORKHISTORY.PERSONRID
WHERE PERSONRID=<some number> AND WORKHISTORY.ROWNUMBER=1
ROWNUMBER needs to be generated for this query on that one table though. So that if we want to access the second WORKHISTORY record's address, we could just go WORKHISTORY.ROWNUMBER=2 and if say we had two address's that matched, we could cycle through the addresses for one WORKHISTORY record using ADDRESS.ROWNUMBER=1 and ADDRESS.ROWNUMBER=2
This should be capable of being an automatically generated query. Thus, there could be more than 10 inner joins in order to get to the relevant table, and we need to be able to cycle through each table's record independently of the rest of the tables..
I'm aware there is the RANK and ROWNUMBER functions, but I'm not seeing how it will work for me because of all the inner joins
note: in this example query, ROWNUMBER should be automatically generated! It should never be stored in the actual table
Can you use a temp table?
I ask because you can write the code like this:
select a.field1, b.field2, c.field3, identity (int, 1,1) as TableRownumber into #temp
from table1 a
join table2 b on a.table1id = b.table1id
join table3 c on b.table2id = c.table2id
select * from #temp where ...

Resources