I have a table A and B with a common ID field. I would like to do a full outer join on these tables, selecting the ID and either 'table A' or 'table B', depending on which table the ID came from.
SELECT ID, ['tableA'|'tableB']
FROM A FULL OUTER JOIN B ON A.ID = B.ID
WHERE A.ID IS NULL OR B.ID IS NULL
Try this:
SELECT COALESCE(A.ID , B.ID) AS ID ,
CASE WHEN A.ID IS NOT NULL AND B.ID IS NULL THEN <tableA results>
WHEN A.ID IS NULL AND B.ID IS NOT NULL THEN <tableB results>
END AS results
FROM A FULL OUTER JOIN B ON A.ID = B.ID
WHERE A.ID IS NULL OR B.ID IS NULL
So this is what I came up with after a little help from Tab.
SELECT ID, SELECT CASE WHEN ID IN (SELECT ID FROM A) THEN 'tableA'
WHEN ID IN (SELECT ID FROM B) THEN 'tableB'
FROM A FULL OUTER JOIN B ON A.ID = B.ID
WHERE A.ID IS NULL OR B.ID IS NULL
Related
Given two tables, is there a name for the result of subtracting inner join from full outer join, both on the same condition? Is it a type of "join"? Thanks.
It is not a type of join in SQL. You can write it as:
select . . .
from a full join
b
on a.id = b.id
where a.id is null or b.id is null;
If you are looking for ids that are in only one table, it can be more efficient to do:
select a.id
from a
where not exists (select 1 from b where b.id = a.id)
union all
select b.id
from b
where not exists (select 1 from a where a.id = b.id);
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';
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
I have to tables (tbla and tblb) with each one col (id):
select * from tbla;
ID
---
1
3
5#A
select * from tblb;
ID
---
2
3
Now I need a full join:
select a.id, b.id
from tbla a
full outer join tblb b on b.id = a.id;
ID ID1
--------
1
3 3
5#A
2
... but without entries containing a #-sign in tbla.id
select a.id, b.id
from tbla a
full outer join tblb b on b.id = a.id
where a.id not like '%#%';
ID ID1
--------
1
3 3
why is the entry with id 2 from tblb missing?
Because when you do a full outer join, columns on either side can end up with a NULL value.
Explicitly check for NULL:
select a.id, b.id
from tbla a
full outer join tblb b on b.id = a.id
where a.id not like '%#%' or a.id is null;
(Originally, I had suggested moving the logic to the on clause. Alas, the full outer join keeps records in both tables, even when no records match the condition. So, moving the condition to the on clause doesn't fix anything.)
When you do outer joins, you have to do your filtering in the from clause. If you do it in the where clause your join effectively becomes an inner join.
So change this:
full outer join tblb b on b.id = a.id
where a.id not like '%#%'
to this
full outer join tblb b on b.id = a.id
and a.id not like '%#%'
You are doing a full join, but by specifying a.id in the where clause, you filter your result set afterwards.
To achieve what you want, you can either move the clause into the join condition:
select a.id, b.id
from tbla a
full outer join tblb b
on b.id = a.id
and a.id not like '%#%';
Or you can use nvl:
select a.id, b.id
from tbla a
full outer join tblb b on b.id = a.id
where nvl(a.id, 'n/a') not like '%#%';
Or explicitly allow NULL values for a.id:
select a.id, b.id
from tbla a
full outer join tblb b on b.id = a.id
where (a.id is null or a.id not like '%#%');
I have table A, B and C
I want to return all entries in table A that do not exist in table B and of that list do not exist in table C.
select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)
this gives me the first result of entries in A that are not in B. But now I want only those entries of this result that are also not in C.
I tried flavours of:
select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)
AND
where not exists (select 1 from table_C as c
where a.id = c.id)
But that isnt the correct logic. If there is a way to store the results from the first query and then select * from that result that are not existent in table C. But I'm not sure how to do that. I appreciate the help.
Try this:
select * from (
select a.*, b.id as b_id, c.id as c_id
from table_A as a
left outer join table_B as b on a.id = b.id
left outer join table_C as c on c.id = a.id
) T
where b_id is null
and c_id is null
Another implementation is this:
select a1.*
from table_A as a1
inner join (
select a.id from table_A
except
select b.id from table_B
except
select c.id from table_c
) as a2 on a1.id = a2.id
Note the restrictions on the form of the sub-query as described here. The second implementation, by most succinctly and clearly describing the desired operation to SQL Server, is likely to be the most efficient.
You have two WHERE clauses in (the external part of) your second query. That is not valid SQL. If you remove it, it should work as expected:
select * from table_A as a
where not exists (select 1 from table_B as b
where a.id = b.id)
AND
not exists (select 1 from table_C as c -- WHERE removed
where a.id = c.id) ;
Tested in SQL-Fiddle (thnx #Alexander)
how about using LEFT JOIN
SELECT a.*
FROM TableA a
LEFT JOIN TableB b
ON a.ID = b.ID
LEFT JOIN TableC c
ON a.ID = c.ID
WHERE b.ID IS NULL AND
c.ID IS NULL
SQLFiddle Demo
One more option with NOT EXISTS operator
SELECT *
FROM dbo.test71 a
WHERE NOT EXISTS(
SELECT 1
FROM (SELECT b.ID
FROM dbo.test72 b
UNION ALL
SELECT c.ID
FROM dbo.test73 c) x
WHERE a.ID = x.ID
)
Demo on SQLFiddle
Option from #ypercube.Thank for the present;)
SELECT *
FROM dbo.test71 a
WHERE NOT EXISTS(
SELECT 1
FROM dbo.test72 b
WHERE a.ID = b.ID
UNION ALL
SELECT 1
FROM dbo.test73 c
WHERE a.ID = c.ID
);
Demo on SQLFiddle
I do not like "not exists" but if for some reason it seems to be more logical to you; then you can use a alias for your first query. Subsequently, you can re apply another "not exists" clause. Something like:
SELECT * FROM
( select * from tableA as a
where not exists (select 1 from tableB as b
where a.id = b.id) )
AS A_NOT_IN_B
WHERE NOT EXISTS (
SELECT 1 FROM tableC as c
WHERE c.id = A_NOT_IN_B.id
)