Multiple Join to single column using ID T-SQL - sql

I have following issue. I'm trying to join three tables:
TableA: Record_id, Reference_id, Param
TableB: Doc_id, NameB
TableC: Doc_id, NameC
depending on value in TableA.Param, I need to select Name from tables B or C by joining on Reference_id
I've tried to use "case" constrain, but didn't worked out :)
select a.Record_id, a.Reference_id
, case when Param = 'B' then b.NameB
when Param = 'C' then c.NameC
from TableA as a inner join
TableB as b on a.Reference_id = b.Doc_id inner join
TableC as c on a.Reference_id = c.Doc_id
Any ideas?

You could left join with that condition and take the first non-null name with coalesce()
select a.Record_id, a.Reference_id,
coalesce(b.NameB, c.NameC) as name
from TableA as a
left join TableB as b on a.Reference_id = b.Doc_id
and Param = 'B'
and b.STAT = 'A'
left join TableC as c on a.Reference_id = c.Doc_id
and Param = 'C'
and c.STAT = 'A'
BTW your query was close (missed the end). This would have worked with left joins
select a.Record_id, a.Reference_id,
case when Param = 'B' then b.NameB
when Param = 'C' then c.NameC
end as name
from TableA as a
left join TableB as b on a.Reference_id = b.Doc_id and b.STAT = 'A'
left join TableC as c on a.Reference_id = c.Doc_id and c.STAT = 'A'

SELECT a.Record_id, a.Reference_id,V.Name
FROM TableA AS a
inner join
(
SELECT Doc_id id, NameB Name,'B' Type from TableB
UNION ALL
SELECT Doc_id ID, NameC name,'C' Type From TableC
) AS V On V.ID=Reference_id AND Type=Param

Try this:
SELECT a.Record_id, a.Reference_id, b.NameB AS Name
FROM TableA AS a
INNER JOIN TableB AS b ON a.Reference_id = b.Doc_id
WHERE a.Param = 'B'
UNION
SELECT a.Record_id, a.Reference_id, c.NameC AS Name
FROM TableA AS a
INNER JOIN TableC as c ON a.Reference_id = c.Doc_id
WHERE c.Param = 'C'

Related

How to replace Union in Sql

I need to concatinate results from 2 tables without using UNION.
Ex : I have 4 tables a, b, c, d. see below snips:
Table a:
Table b:
Table c:
Table d:
I am concatinating a and d results using UNION ALL like below:
select a.id,a.seq,a.item,b.des,c.qty from a
left join b on a.item = b.item
left join c on a.id = c.id and a.seq = c.seq
UNION ALL
select d.id,d.seq,d.item,d.des,c.qty from d
join c on d.id = c.id and d.seq = c.seq
My output:
But I need same result without using UNION ALL.
Is it possible if so HOW?
You can apply Full Outer join instead of Union which has its similarities to Union
SELECT a.id,a.seq,a.item,b.des,c.qty
FROM a left join b on a.item = b.item
left join c on a.id = c.id and a.seq = c.seq
FULL OUTER JOIN
(
SELECT d.id,d.seq,d.item,d.des,c.qty
FROM d join c on d.id = c.id and d.seq = c.seq
)x ON a.id = x.id
You can replace union all with full join with a "false" condition and lots of COALESCE()s.
The logic looks like this:
SELECT COALESCE(abc.id, cd.id) as id,
COALESCE(abc.seq, cd.seq) as seq,
COALESCE(abc.item, cd.item) as item,
COALESCE(abc.des, cd.des) as eesc,
COALESCE(abc.qty, cd.qty) as qty
FROM (SELECT a.id, a.seq, a.item, b.des, c.qty
FROM a LEFT JOIN
b
ON a.item = b.item LEFT JOIN
c
ON a.id = c.id AND a.seq = c.seq
) abc FULL JOIN
(SELECT d.id, d.seq, d.item, d.des, c.qty
FROM d JOIN
c
ON d.id = c.id AND d.seq = c.seq
) dc
ON 1 = 0; -- never evaluates to true
There is a LEFT JOIN from table 'a' to table 'c' (on 'id' and 'seq' columns) in the upper query and INNER JOIN from table 'd' to table 'c' in the lower query. Therefore I think you could LEFT JOIN from table 'c' to table 'd' and it would produce the correct output.
select a.id,a.seq,a.item,b.des,c.qty
from a
left join b on a.item = b.item
left join c on a.id = c.id and a.seq = c.seq
left join d on c.id = d.id and c.seq = d.seq;
If you want you can use INSERT INTO a (tmp) table and get the same result in a table.

Combining values from multiple tables using join clause with multiple ON

I want to combine all the related data using LEFT JOIN clause but if one of tables has no matched record from other table it will not show up. Can you check my queries it seems that there is missing or totally messed up. Here's my query.
SELECT*
FROM
MASTER_TBL
LEFT JOIN
(
SELECT*
FROM
TBLA A
LEFT JOIN
TBLB B
ON
A.ID=B.ID AND A.DESC=B.DESC
LEFT JOIN
TBLC C
ON
B.ID=C.ID AND B.DESC=C.DESC
LEFT JOIN
TBLD D
ON
C.ID=D.ID AND C.DESC=D.DESC
) E
ON
MASTER_TBL.ID=E.ID
The problem is that you are cascading the conditions across joins. For example, here are the join conditions for table d:
C.ID = D.ID AND C.DESC = D.DESC
For this to match, you need to have a matching row in C already.
As your query stands, it looks like you can use the id from the master table to search all the following tables. As for the desc columns, it looks like your best pick is to use that of table a.
So, consider:
select *
from master_tbl m
left join tbla a on a.id = m.id
left join tblb b on b.id = m.id and b.desc = a.desc
left join tblc c on c.id = m.id and c.desc = a.desc
left join tbld d on d.id = m.id and d.desc = a.desc
If all descs are not available in tablea, we could switch to full joins. The logic is more complicated to follow, but that would look like:
select *
from master_tbl m
full join tbla a on a.id = m.id
full join tblb b on b.id = m.id and b.desc = a.desc
full join tblc c on c.id = m.id and c.desc = coalesce(a.desc, b.desc)
full join tbld d on d.id = m.id and d.desc = coalesce(a.desc, b.desc, c.desc)
This approach uses UNION ALL to combine the letter named tables (tbla, tblb, tblc, tbld) into a CTE, common table expression. The combined table is then summarized by id, [desc] and crosstabulated (or pivoted) across the login columns. The pivoted result is then LEFT JOIN'ed to the master_tbl. Something like this.
with
tbl_cte(tbl, id, [login], [desc]) as (
select 'A', * from tbla
union all
select 'B', * from tblb
union all
select 'C', * from tblc
union all
select 'D', * from tblc),
pvt_cte(id, tbla_login, tblb_login, tblc_login, tbld_login, [desc]) as (
select id,
max(case when tbl='A' then [login] else null end) as tbla_login,
max(case when tbl='B' then [login] else null end) as tblb_login,
max(case when tbl='C' then [login] else null end) as tblc_login,
max(case when tbl='D' then [login] else null end) as tbld_login,
[desc]
from tbl_cte
group by id, [desc])
select mt.id, [name], country, [status], pc.tbla_login,
pc.tblb_login, pc.tblc_login, pc.tbld_login, pc.[desc]
from master_tbl mt
left join pvt_cte pc on mt.id=pc.id;

Conditional join in SQL Server dependent on other table values

I need make a decision which table should be use in join statement depend on values in another table
I tried using CASE and COALESCE but can't achieve any success.
TableA has A and B and C and many other columns
TableB has ID and NAME columns
TableC has ID and NAME columns
My select statement is;
Select A.D, A.E, A.F From TableA A
If A.E = 1 then the following join should be used
left outer join TableB B ON A.B = B.ID
and B.NAME should be returned in the select statement
If A.E = 2 then the following join should be used
left outer join TableC C ON A.B = C.ID
and C.NAME should be returned in the select statement
Just add your conditions to the joins, and then use a case statement to pull the correct field to your result set e.g.
select A.D, A.E, A.F
, case when B.[Name] is not null then B.[Name] else C.[Name] end [Name]
from TableA A
left outer join TableB B ON A.B = B.ID and A.E = 1
left outer join TableC C ON A.B = C.ID and A.E = 2
Join tablea with the union of tableb with an extra column with value 1 and tablec with an extra column with value 2 and apply the conditions in the ON clause:
select
a.D, a.E, a.F, u.NAME
from tablea a
left join (
select *, 1 col from tableb
union all
select *, 2 col from tablec
) u on a.B = u.id and a.E = u.col

Looking through 3 tables

I am working on a personal project.
I have the following data
tbl A
id, blah, blah
tbl B
id, id_2
tbl C
id_2, Result
I have check for the following, if id in tbl A exists in tbl B AND if Pass = 'A'.
I can write a query to check for the keys in A exists in B.
Something like,
SELECT * FROM tblA as a
WHERE NOT EXISTS (
SELECT * FROM tblB as b
WHERE a.id = b.id)
And this works fine.
I can also write something with an INNER JOIN
SELECT *
FROM tabC
INNER JOIN tblB ON tblC.id2 = tblB.id2
INNER JOIN tblA ON tblB.id = tblA.id
WHERE Result = 'A' GROUP BY id
But I can't seem to figure out how to combine both these queries together.
you can try like below
SELECT c.*
FROM tabC c
INNER JOIN tblB b ON c.id2 = b.id2
INNER JOIN tblA a ON b.id = a.id
WHERE Result = 'A'
and NOT EXISTS (
SELECT 1 FROM tblB as b1
WHERE a.id = b1.id)

return pair of values instead of one value from two queries

I've got two queries that return single result.
They look something like this
// query 1
SELECT A.id FROM tableA A
INNER JOIN tableB B
ON B.id = A.id
WHERE b.status = 'ACTIVE'
// query 2
SELECT C.id FROM tableC C
WHERE c.status = 'ACTIVE'
How to combine them and make return the pair of values instead of one value from different queries? I mean to get something like [A.id, C.id]
Currently I have to use two queries in the applications and I want to combine them into one.
I think like this will do
SELECT (SELECT A.id FROM tableA A
INNER JOIN tableB B
ON B.id = A.id
WHERE b.status = 'ACTIVE'
) as 'query1',
(
SELECT C.id FROM tableC C
WHERE c.status = 'ACTIVE'
) as 'query2'
As your question is not clear, so i assume that you either needids from mentioned queries in one row or in different rows, you can use union all/union (provided that datatypes are compatible or implicitly convertible and duplicates or allowed or not) as below.
Combining Result in different rows.
SELECT A.id
FROM tableA A
INNER JOIN tableB B
ON B.id = A.id
WHERE b.status = 'ACTIVE'
union all
SELECT C.id
FROM tableC C
WHERE c.status = 'ACTIVE'
Combining Result in Single Row.
select max(id1), max(id2)
from(
SELECT A.id as id1, NULL as id2
FROM tableA A
INNER JOIN tableB B
ON B.id = A.id
WHERE b.status = 'ACTIVE'
union all
SELECT NULL, C.id
FROM tableC C
WHERE c.status = 'ACTIVE'
) t;
SAMPLE DEMO
You can run following query which work fine for me:
select t1.id as aid ,t2.id as cid
from (
SELECT A.id
FROM tableA A
INNER JOIN tableB B ON B.id = A.id
WHERE b.status = 'ACTIVE'
) t1
full outer join (
SELECT C.id
FROM tableC C
WHERE c.status = 'ACTIVE'
) t2 on t1.id=t2.id
You can join your second query with your first query as follows, so that you will get two (A.id, C.id) values in one query...
SELECT A.ID,C.ID FROM
(SELECT A.ID FROM table_A A INNER JOIN
table_B B ON A.ID=B.ID WHERE B.STATUS='A')A
INNER JOIN table_c C
ON C.ID=A.ID WHERE C.STATUS='A';