How to join 3 tables in sql with or condition - sql

I have 3 tables:
table1
inner join with table2; or:
inner join with table3
The query:
select table1.x
from table1 right outer join
table2
on table1.x = table2.x right outer join
table3
on table1.x = table3.x
but I can only see x values that are in both table2 and table3

Use left join, not right join, along with an appropriate filter condition:
select table1.x
from table1 left join
table2
on table1.x = table2.x left join
table3
on table1.x = table3.x
where table2.x is not null or table3.x is not null;
You might consider writing this using exists:
select t1.*
from table1 t1
where exists (select 1 from table2 t2 where t2.x = t1.x) or
exists (select 1 from table3 t3 where t3.x = t1.x);
That seems like a more natural way to implement your logic -- and you won't get duplicates when x is duplicated in table2 or table3.

Related

How do I look for non-matching values across 3 SQL tables?

I'm looking to do what I believe is a double-nested check across three tables, but have no idea how to do so.
I have Table1, Table2, and Table3.
All are tied by an ID and a "Longform" and "Shortform" in Table1:
I'm trying to find:
Entries whose IDs appear in Table2 that have the same Longform as those in Table3, but don't share the same Shortform.
This is about as far as I've gotten:
SELECT T2.Longform,T2.Shortform FROM(
SELECT Table1.Longform,Table1.Shortform,Table1.ID FROM OuterTable1.Table1
LEFT JOIN OuterTable2.Table2 on Table1.ID = Table2.ID)
WHERE Table2.ID IS NOT NULL) T2
;
I know I'm probably going to have to do another nested select, or a join, on Outertable3.Table3 but I'm not sure which... Or where...
Any help appreciated as always.
Try the following:
Select *
(
Select T1.*
from T2
inner join T1
on T1.ID = T2.ID
) as Tab
inner join
(
Select T1.*
from T3
inner join T1
on T1.ID = T3.ID
) as Tab2
on Tab.id = Tab2.id
and Tab.Longform = Tab2.Longform
and Tab.Shortform <> Tab2.Shortform
To get the longform join table1 to table2 or table3. Then use EXISTS to check in a subquery if the IDs of table1 are different but the longform is equal.
SELECT *
FROM table2 t21
INNER JOIN table1 t11
ON t11.id = t21.id
WHERE EXISTS (SELECT *
FROM table3 t32
INNER JOIN table1 t12
ON t12.id = t32.id
WHERE t12.id <> t11.id
AND t12.longform = t11.longform);
Assuming ID is unique in all three tables
Select t2.id,t2.shortform, t1.shortform AS shortformTab1, t2.longform
FROM table2 t2
JOIN table3 t3
ON t2.id = t3.id AND t2.longform = t3.longform
JOIN table1 t1
ON t2.id = t1.id AND t2.shortform != t1.shortform

How do I get the results of one JOIN and THEN feed those into a separate join in T-SQL?

I'm trying to JOIN 2 tables ON a key like
SELECT column1,column2
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.t2id = t2.id
Now, I have a 3rd table that has a Foreign Key with t2's id that I want to join... When I do
LEFT JOIN
Table3 t3 ON t3.t2id = --<-------------- This is where I'm lost
I don't know if I should do ON t3.t2id = t1.t2id OR ON t3.t2id = t2.id
What I need is the list of t2ids which are still in the picture after the first join. However, it seems as though if I specify either of the above, it will just pull ids from the original table before the first join?
To clarify one more time: I'm trying to essentially do a INNER JOIN of Table1 and Table2, get the resulting table, then get the t2ids of those results and feed them into a final join such that the final result contains all of Table3's rows as well as the data from the first join
You said: "final result contains all of Table3's rows as well as the data from the first join".
It means that you need
Table3 LEFT JOIN <previous results>
instead of
<previous results> LEFT JOIN Table3
The easiest way to write it is to use Common-Table Expressions:
WITH
CTE_InnerJoin
AS
(
SELECT column1, column2, t1.t2id
FROM
Table1 t1
INNER JOIN Table2 t2 ON t1.t2id = t2.id
)
SELECT
CTE_InnerJoin.column1
,CTE_InnerJoin.column2
,Table3....
FROM
Table3
LEFT JOIN CTE_InnerJoin ON CTE_InnerJoin.t2id = Table3.t2id
;
It doesn't matter what column you include in the CTE: t1.t2id or t2.id, the values in them are the same, because they are inner-joined together.
JOINs already do exactly what you want. A JOIN isn't always between two tables. Frequently, it's between the results of previous joins.
SELECT column1,column2
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.t2id = t2.id
LEFT JOIN
Table3 t3 ON t3.t2id = t2.id
At the point at which you're writing the final ON clause here, what you're joining is precisely the results of the previous INNER JOIN on the left and the table Table3 on the right. All of t1, t2 and t3 are in scope within the ON clause, but note that t1 and t2 are now both used as aliases into the same source of rows - the previous INNER JOIN.
As a further example, consider the "diamond join":
SELECT
*
FROM
t1
left join
t2
on
t1.a = t2.b
left join
t3
on
t1.c = t3.d
inner join
t4
on
t2.e = t4.f OR
t3.g = t4.h
This is a way of joining two tables (t1 and t4) based on two alternative joins. Note that in the final inner join, what is on the "left" is the result of already joining tables t1, t2 and t3.
Join the table having foreign key with
Try this....
SELECT column1,column2
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.t2id = t2.id
LEFT join Table3 t3 ON t2.id=t3.t2id
Or Like this.
SELECT t12.column1 ,
t12.column2 ,
t3.*
FROM (
--- INNER JOIN of Table1 and Table2, get the resulting table,
SELECT t1.column1 ,
t2.column2 ,
t1.t2id --- or t2.id doesn't matter because its inner join
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.t2id = t2.id
) T12
LEFT JOIN Table3 T3 ON t3.t2id = t1.t2id --- then get the t2ids of those results
--- and feed them into a final join
--- if you want to get all rows from Table3, Change LEFT JOIN Table3 T3 ON t3.t2id = T1.t2id
--- into RIGHT JOIN Table3 T3 ON t3.t2id = T1.t2id
try this
select t3.*, column1, column2
from
table1 t1 inner join table2 t2 on t1.t2id = t2.id
right outer join table3 t3 on t3.t2id = t2.id
equvalent to
select t3.*, column1, column2
from
table1 t1 inner join table2 t2 on t1.t2id = t2.id
right outer join table3 t3 on t3.t2id = t1.t2id
if you want all rows from table 3 and those matching rows from table1 inner joined to table2 then you can use this syntax:
select t3.*,
column1, column2
from table3 t3
left join table2 t2
inner join table1 t1
on t1.t2id = t2.id
on t3.t2id = t2.id

Applying joins conditionally in SQL Server

I have some set of records, but now i have to select only those records from this set which have theeir Id in either of the two tables.
Suppose I have table1 which contains
Id Name
----------
1 Name1
2 Name2
Now I need to select only those records from table one
which have either their id in table2 or in table3
I was trying to apply or operator witin inner join like:
select *
from table1
inner join table2 on table2.id = table1.id or
inner join table3 on table3.id = table1.id.
Is it possible? What is the best method to approach this? Actually I am also not able to use
if exist(select 1 from table2 where id=table1.id) then select from table1
Could someone help me to get over this?
Use left join and then check if at least one of the joins has found a relation
select t1.*
from table1 t1
left join table2 t2 on t2.id = t1.id
left join table3 t3 on t3.id = t1.id
where t2.id is not null
or t3.is is not null
I would be inclined to use exists:
select t1.*
from table1 t1
where exists (select 1 from table2 t2 where t2.id = t1.id) or
exists (select 1 from table3 t3 where t3.id = t1.id) ;
The advantage to using exists (or in) over a join involves duplicate rows. If table2 or table3 have multiple rows for a given id, then a version using join will produce multiple rows in the result set.
I think the most efficient way is to use UNION on table2 and table3 and join to it :
SELECT t1.*
FROM table1 t1
INNER JOIN(SELECT id FROM Table2
UNION
SELECT id FROM Table3) s
ON(t.id = s.id)
Alternatively, you can use below SQL as well:
SELECT *
FROM dbo.Table1
WHERE id Table1.IN ( SELECT table2.id
FROM dbo.table2 )
OR Table1.id IN ( SELECT table3.id
FROM Table3 )

SQL join order and conditions

I've got 3 tables that I want to join and filter on some conditions.
I've first wrote this query:
select * from table1 t1
left join (select * from table2 where table2.fieldX=...) t2
on t1.id_12=t2.id_12
left join table3
on t2.id_23=t3.id_23
where t1.fieldY=...
Then I wanted to make it looks like more canonical by rewritting it like that:
select * from table1 t1
left join table2 t2
on t1.id_12=t2.id_12
left join table3
on t2.id_23=t3.id_23
where table2.fieldX=...
and t1.fieldY=...
But it does not give the same result.
I dont't understand why...
Do you?
Thanks in advance.
When you put table2.fieldX=... in the where clause you eliminate all rows from table1 that do not have a corresponding row in table2. Effectively you are changing the left join into an inner join.
Instead, you can apply the table2 filter in the join itself:
SELECT
*
FROM
Table1 t1
LEFT JOIN Table2 t2 ON t1.id_12 = t2.id_12 AND t2.fieldX = ...
LEFT JOIN Table3 t3 ON t2.id_23 = t3.id_23
WHERE
t1.fieldY = ...
Did you add the inner select where on the second query?
SELECT *
FROM table1 t1
LEFT JOIN table2 t2
on t1.id_12=t2.id_12
LEFT JOIN table3
on t2.id_23=t3.id_23
WHERE t1.fieldY=...
and t2.fieldX=...

SQL query - filter primary keys

I am using microsoft sql server and my query is of the following format (table1 primary key is (A,B)):
Select table1.A, table1.B, table2.C, Table3.D
from table1
left outer join table2 on table1.A = table2.A
left outer join tabl3 on table1.B = table3.B
//Here comes the question
//Except (A,B) in ( select A,B from BadTable)
How could I do it nicely? I was thinking about finding the set of CORRECT keys using sth like (cannot use except - running sql server 2000)
Select A,B
from table1
not exists ( select A,B from bad table)
and then inner join that with the main query. What do you think?
Select table1.A, table1.B, table2.C, Table3.D
from table1 T1
left outer join table2 on table1.A = table2.A
left outer join tabl3 on table1.B = table3.B
where not exists (select 1 from badTable where A = T1.A and B = T1.B)
would be a good way
Select table1.A, table1.B, table2.C, Table3.D ,badtable.*
from table1
left join table2 on table1.A = table2.A
left join table3 on table1.B = table3.B
left join badtable on table1.a = badtable.a
and table1.b = badtable.b
where badtable.a is null