I need to join an ID# field from tableA to the ID# field in tableB so I can join the NAME field in tableB to the NAME field in tableC. Currently using CTE's and I would like to accomplish this without the need of a CTE.
Currently doing:
WITH t
AS
(
SELECT tableB.ID#
FROM tableA
INNER JOIN tableB ON (tableA.ID_REF# = tableB.ID_REF#)
),
u as
(
SELECT NAME
FROM tableC
)
SELECT u.NAME
FROM t
INNER JOIN u ON (t.ID# = u.ID#)
I'm assuming I'm able to do the same thing with a nested join?
join an ID # field from tableA to the ID # field in tableB so I can join the NAME field in table B to the NAME field in tableC.
Why use CTEs? Just chain the JOINs:
SELECT . . . -- whatever you want here
FROM tableA a JOIN
tableB b
ON a.ID_REF# = b.ID_REF# JOIN
tableC c
ON b.Name = c.Name;
Indeed, you don't need a CTE - you can join twice. Based on your problem statement, that would be:
select c.name
from tableC c
inner join tableB b on b.name = c.name
inner join tableA a on a.id# = b.id#
Inner join outputs the same result no matter the order of join ( a -> b -> c, c -> b -> a). Also note that default join without any keyword will be inner join.
So you can do like this (c->a->b):
select ...
from tableC c
join tableB b on b.name = c.name
join tableA a on a.ID_REF# = b.ID_REF#
or this (a->b->c):
select ...
from tableA a
join tableB b on a.ID_REF# = b.ID_REF#
join tableC c on b.name = c.name
Declare #TableA table (ID int ,Name nvarchar(50))
Declare #TableB table(ID int, Name nvarchar(50))
Declare #TableC table (ID int , Name nvarchar(50))
insert into #TableA values(1,'Chit'),(2,'Mar'),(3,'Thiri')
insert into #TableB values(1,'Chit'),(2,'Mar'),(3,'Thiri')
insert into #TableC values(1,'Chit'),(2,'Mar'),(3,'Thiri')
select c.ID,c.Name from #TableC c inner join (select b.Name from #TableA a inner join #TableB b on a.ID =b.ID Group by b.Name) bb on bb.Name=c.Name
Related
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
I have two tables, tableA which has a list of records and tableB which has restrictions (if any). How can I join the tables that will essentially be an inner join if there are records in tableB or no join if tableB is empty?
ie:
tableA
id | name
1 | val1
2 | val2
tableB (with restrictions)
id | name | userID
1 | val1 | 123
OR tableB (no restrictions)
id | name | userID
is this possible? My attempt below:
SELECT a.*
FROM tableA a
INNER JOIN (CASE WHEN select 1 from tableB = 1 THEN tableB ELSE tableA END) b
ON a.id = b.id
where userID = XXX
EDIT: There is a check on tableB
Just use a left join
SELECT a.*
FROM tableA a
LEFT JOIN tableB b = ON a.id = b.id and b.userid = xxx
I'm not seeing any complexity beyond that at present - given the simplicity of the statement in the original question, I am wondering if you are putting WHERE predicates against the table B - if you are, they need to be in the ON clause of the join
Edited to include your where clause moved.
For empty rows, u can use same query for both restrictions.
I guess you are usign SQL server
Use left join to pull rows if table b is blank
select a.id,a.name
from tableA a left join tableB on a.id = b.id
Demo:
declare #tableA table (id int, name varchar(10))
insert into #tableA
select 1, 'name'
union all
select 2,'name1'
union all
select 3,'name2'
declare #tableb table (id int, name varchar(10))
select a.id,a.name
from #tableA a left join #tableb b on a.id = b.id
this will pull all records from tableA if tableB is empty and only matching records if it is not:
select a.id, a.name
from tableA a
join tableB on a.id = b.id
where exists (select 1 from tableB)
union all
select a.id, a.name
from tableA a
where not exists (select 1 from tableB)
I have two tables: A (a_id as int, some string fields...) and B (b_id, string field "name" and referenced column a_id).
I want to select unique values from the table A where B.name LIKE "%somestring%".
You could use EXISTS:
SELECT a.*
FROM TableA a
WHERE EXISTS
(
SELECT 1 FROM TableB b
WHERE a.a_id = b.a_id
AND b.name LIKE "%somestring%"
)
you can use inner join to do this.
select A.a_id, B.b_id, from A inner join B on A.a_id = B.a_id where B.Name LIKE '%somestring%'
I have been having a hard time googling an answer for this, but....
can someone explain to me the difference between putting the ON condition of a JOIN with the the JOIN itself vs putting the ON at the end of all the other JOINs.
here is an example http://sqlfiddle.com/#!3/e0a0f/3
CREATE TABLE TableA (Email VARCHAR(100), SomeNameA VARCHAR(100))
CREATE TABLE Tableb (Email VARCHAR(100), SomeNameB VARCHAR(100))
CREATE TABLE Tablec (Email VARCHAR(100), SomeNameC VARCHAR(100))
INSERT INTO TableA SELECT 'joe#test.com', 'JoeA'
INSERT INTO TableA SELECT 'jan#test.com', 'JaneA'
INSERT INTO TableA SELECT 'dave#test.com', 'DaveA'
INSERT INTO TableB SELECT 'joe#test.com', 'JoeB'
INSERT INTO TableB SELECT 'dave#test.com', 'DaveB'
INSERT INTO TableC SELECT 'joe#test.com', 'JoeC'
INSERT INTO TableC SELECT 'dave#test.com', 'DaveC'
SELECT TOP 2 a.*,
b.*,
c.*
FROM TableA a
LEFT OUTER JOIN TableB b
ON a.email = b.email
INNER JOIN TableC c
ON c.Email = b.email;
SELECT TOP 2 a.*,
b.*,
c.*
FROM TableA a
LEFT OUTER JOIN TableB b
INNER JOIN TableC c
ON c.Email = b.email
ON a.email = b.email;
I don't understand why these two SELECT statements produce different results.
What matters is orders of joins. Treat your expressions as if every join produced temporary "virtual" table.
So when you write
FROM TableA a
LEFT OUTER JOIN TableB b ON a.email = b.email
INNER JOIN TableC c ON c.Email = b.email ;
then order is as follows:
TableA is left joined to TableB producing temporary relation V1
V1 is inner joined to TableC.
Meanhwile when you write:
FROM TableA a
LEFT OUTER JOIN TableB b
INNER JOIN TableC c ON c.Email = b.email ON a.email = b.email;
then order is as follows:
TableB is inner joined to TableC producing temporary relation V1.
TableA is left joined to V1.
Thus results are different. It is generally recommended to use parenthesis in such situations to improve readability of the query:
FROM TableA a
LEFT OUTER JOIN
(TableB b INNER JOIN TableC c ON c.Email = b.email)
ON a.email = b.email;
In your second example, the part ON a.email = b.email belongs to the LEFT JOIN.
If written like this, it means the following:
INNER JOIN TableC with TableB and LEFT OUTER JOIN the result with TableA.
The result will be all rows from TableA joined with those rows from TableB that also have an entry in TableC.
The first example means the following:
LEFT OUTER JOIN TableB with TableA and INNER JOIN TableC with the result. This is equivalent to using an INNER JOIN for TableB.
Explanation: When you LEFT OUTER JOIN TableA with TableB you will get all rows from TableA and for matching rows in TableB you will get that data, too. In your result set you will have rows with b.email = NULL and this will now be INNER JOINed with TableC. As long as there is no entry in TableC with email = NULL you will get the results you observed.
I'm facing with a join problem in sql server 2005 database.
I've the following tables structure:
TableA --LEFT JOIN--> TableB --INNER JOIN-->TableC
So if I write a query like this:
SELECT TableA.* FROM TableA
LEFT OUTER JOIN TableB ON TableA.keyOfB = TableB.key
INNER JOIN TableC ON TableB.keyOfC = TableC.key
where TableA.key = aValue
it read 0 record if there's not any TableB record associated with TableA record.
But TableB is in outer join, so this is not what I expected. In other words, the INNER JOIN shouldn't have been considerer because there's not any TableB record!
What I'm missing?
I think it has to do with the order of JOIN operations.
The result of (A LEFT OUTER JOIN B) INNER JOIN C, you want A LEFT OUTER (B INNER JOIN C).
Try dropping some () in there.
Or try reordering your JOINS to ... B INNER C RIGHT OUTER A to get (B INNER C) RIGHT OUTER A.
EDIT:
Example of what I was thinking:
SELECT TableA.* FROM TableA
LEFT OUTER JOIN (TableB INNER JOIN TableC ON TableB.keyOfC = TableC.key)
ON TableA.keyOfB = TableB.key
WHERE TableA.key = aValue
Flipping to RIGHT OUTER:
SELECT TableA.* FROM TableB
INNER JOIN TableC ON TableB.keyOfC = TableC.key
RIGHT OUTER JOIN TableA ON TableA.keyOfB = TableB.key
WHERE TableA.key = aValue
NOTE: Forgive me if this is doesn't work, I haven't touched SqlServer since version 7.
This is behaving exactly as it should. Your link with TableC is through TableB so the link will not be connected if no TableB record.
Changing INNER JOIN to LEFT OUTER as well - although it is really an inner as far as the data concerned.
If you run query without INNER JOIN, there will be all records with TableB.key null, right? So next INNER JOIN can't find any matching record, that's why there is no result.
Use a virtual table for (B+C) join.
EDIT: Something like:
SELECT TableA.* FROM TableA
LEFT OUTER JOIN
(select key from TableB INNER JOIN TableC ON TableB.keyOfC = TableC.key) as TableBC
ON TableA.keyOfB = TableBC.key
where TableA.key = aValue
Here is the code as an example of using left out join for both table b and c.
declare #TableA table (Adata1 char(2), Adata2 char(2))
declare #TableB table (Bdata1 char(2), Bdata2 char(2))
declare #TableC table (Cdata1 char(2), Cdata2 char(2))
;Insert #TableA
Select 'A', 'A' union all
Select 'B', 'B' union all
Select 'C', 'C'
;Insert #TableB
Select 'Ab', 'Ab' union all
Select 'B', 'B' union all
Select 'C', 'C'
;Insert #TableC
Select 'A', 'A' union all
Select 'B', 'B' union all
Select 'Cb', 'Cb'
--Select * From #TableA
--Select * From #TableB
--Select * From #TableC
Select * from #TableA
LEFT OUTER JOIN #TableB on Adata1 = Bdata1
LEFT OUTER JOIN #TableC on Bdata1 = Cdata1
Results are:
Adata1 Adata2 Bdata1 Bdata2 Cdata1 Cdata2
A A NULL NULL NULL NULL
B B B B B B
C C C Cb NULL NULL