Join tables that might not have records - sql

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)

Related

SQL query to select from one table based on a column value in other table

I have two tables and I want to select all values from "TABLE A" that have a different value in a column from "TABLE B".
I tried this
SELECT A.* FROM tableA A
left join tableB B ON A.id = B.id WHERE B.column <> 1;
But this just return the value that I want to ignore.
SELECT A.*
FROM tableA A
INNER JOIN tableB B
ON A.id = B.id
WHERE B.column != 1;
or
SELECT A.* FROM tableA A WHERE A.Id NOT IN (SELECT B.Id FROM tableB B WHERE B.column != 1)
Depends on your SQL you can use <> or !=
I would suggest not exists:
SELECT A.*
FROM tableA A
WHERE NOT EXISTS (SELECT 1 FROM tableB B WHERE A.id = B.id AND B.column = 1);
Using a JOIN can result in duplicated rows, if more than one row in B matches the JOIN condition.

Need help using a nested join

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

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

Nested SELECT with multiple JOINS

I have trouble writing a SQL statement which will join multiple columns and add on them another select.
I have:
TableA | TableB | TableC
idA | idB | idC
state | idA | idB
| created_time|
And I want to find all rows where state=CLOSED and created_time is the newest.
So I managed to write these 2 queries:
SELECT TableA, TableB, TableC
FROM TableB
JOIN TableA ON TableB.idA = TableA.id
JOIN TableC ON TableB.id = TableC.idB
WHERE TableA.state = 'CLOSED';
And another query which should find the newest Date:
SELECT t.id, t.created_time, t.idA
FROM TableB t
INNER JOIN
(SELECT id, idA, MAX(created_time) AS MaxDate
FROM TableB
GROUP BY id) tm ON t.id = tm.id AND t.created_time = tm.MaxDate
But I have no clue how to concatenate these queries and make SET(state="OPEN") on them.
Can anyone help?
I think DISTINCT ON does what you want:
SELECT DISTINCT ON (a.id) . . .
FROM TableA a JOIN
TableB b
ON b.idA = a.id JOIN
TableC c
ON b.id = c.idB
WHERE a.state = 'CLOSED'
ORDER BY a.id

XOR JOIN in SQL

I have the following tables
Table A
ID "Other Columns"
1
2
3
Table B
ID "Other Columns"
3
4
5
What is the efficient way to return the below result?
Result
ID "Other Columns"
1
2
4
5
A full outer join should work, and only go through each table once. They can be tricky, so test carefully!
SELECT
isnull(A.ID, B.ID) ID
,"Other columns" -- Handle nulls properly!
from TableA A
full outer joing TableB B
on B.ID = A.ID
where not (A.ID is not null
and B.ID is not null)
You want to use left and right join and union them
Select TableA.ID as 'ID','Other Colums'
FROM TableA Left join TableB
ON TableA.ID=TableB.ID
WHERE TableB.ID IS NULL
UNION
Select TableB.ID as 'ID','Other Colums'
FROM TableA Right join TableB
ON TableA.ID=TableB.ID
WHERE TableA.ID IS NULL
You can try like this
SELECT
COALESCE(a.id, b.id),
OtherColumns
FROM #tablea a
FULL JOIN #tableb b
ON a.id = b.id
WHERE a.id IS NULL
OR b.id IS NULL
You can do this with a UNION ALL using a LEFT JOIN to determine if the ID is not in the other table. Keep in mind that the column count and datatypes between the two tables must match up:
Select A.Id, A.OtherColumns
From TableA A
Left Join TableB B On A.Id = B.Id
Where B.Id Is Null
Union All
Select B.Id, B.OtherColumns
From TableB B
Left Join TableA A On A.Id = B.Id
Where A.Id Is Null
Not quite sure what you need with the "Other columns", but you could use EXCEPT:
Select ID from TableA
EXCEPT
Select ID from TableB
If you need Other columns from TableA you could use:
Select ID, OtherColumn1, OtherColumn2 from TableA
where ID not in (select ID from TableB)
(as long as ID cannot be null in TableB)
I broke down each part to be clearer!
select *
into #temp
from
TabA Full outer join TabB
on TabA.ColNameA = TabB.ColNameB
select *
into #temp2
from #temp
where (ColNameA is Null Or ColNameB is null)
select ColNameA from #temp2
where ColNameA Is not null
union
select ColNameB from #temp2
where ColNameB Is not null