SQL join problem - sql

I want to retrieve all records from one table when there are no matches in the second table.
So it is kind of the opposite of an inner join.

You need a LEFT JOIN WHERE IS NULL query (aka outer join):
SELECT table1.*
FROM table1
LEFT OUTER JOIN table2
ON table1.id = table2.id
WHERE table2.id IS NULL
Or a NOT IN:
SELECT *
FROM table1
WHERE id NOT IN (SELECT id FROM table2)

You have three options:
Correlated sub-query.
SELECT * FROM TableA
WHERE NOT EXISTS
(SELECT * FROM TableB WHERE TableB.ID = TableA.ID)
Non-correlated sub-query.
SELECT * FROM TableA
WHERE ID NOT IN (SELECT ID FROM TableB)
OUTER JOIN with NULL elimination.
SELECT * FROM TableA
LEFT [OUTER] JOIN TableB
ON TableA.ID = TableB.ID
WHERE TableB.ItsPrimaryKey IS NOT NULL
In the last example some DBMSes require the word OUTER, some permit it, and some do not allow it at all.
Depending on the DBMS, the various options might produce different execution plans and different performance. Select the one with good performance and that best expresses your intent.

It's an outer join:
SELECT *
FROM tableA AS a
LEFT JOIN tableB AS b USING(x)
Say you have:
tableA:
a | x
-----
1 | 1
3 | 3
table B:
b | x
-------
1 | 'a'
2 | 'b'
then the query above will give you
a | b | x
------------
1 | 'a' | 1
3 | NULL | 3
if you want
a | b | x
----------------
1 | 'a' | 1
NULL | 'b' | 2
3 | NULL | 3
you have to use FULL OUTER JOIN instead of LEFT JOIN.
EDIT: As Larry Lustig told me (and I think is correct after rereading the question) the OP does not want any rows from B. So the query should be:
SELECT a.*
FROM tableA AS a
LEFT JOIN tableB AS b USING(x)
WHERE b.x IS NULL
that will yield
a | x
-------
3 | 3

The "opposite" of inner join is called outer join.

Outer join. Technically possibly FULL OUTER JOIN ;)

Adding to the Solution of Johannes Weiß the solution to your other question about finding objects in table a without objects in table b:
SELECT *
FROM tableA AS a
LEFT JOIN tableB AS b
USING(x)
WHERE b.foo IS NULL

You are looking for LEFT JOIN or FULL OUTER JOIN
Not all DBMS support FULL though.
Simulation of it is possible with UNION, example in MySQL:
SELECT * FROM t1
LEFT JOIN t2 ON t1.id = t2.id
UNION
SELECT * FROM t1
RIGHT JOIN t2 ON t1.id = t2.id

I believe you are looking for FULL OUTER JOIN (works with Oracle 9i+).
EDIT: didn't read your question well... LEFT JOIN if you only want NULL values for the second table

Related

SQL Join Not Exists

I have the following between these two tables, id column and case column
Left Table Right Table
| id1 | case#1 | | case#1 | id1 |
| id2 | case#1 | | case#1 | id3 |
| id3 | case#2 | | case#2 | id1 |
As you can see case#1 is not assigned to id2 on the right table, therefore I would like to pull the (id2, case#1) record from the left table.
You would need to perform an OUTER JOIN with a multiple JOIN condition:
left_table as l right outer join right_table as r
on l.id = r.id and l.case_ = r.case_
where l.id IS NULL;
This will return non-matching rows from the left table
Have you tried a left join?
LEFT OUTER JOIN table ON table1.field1 = table2.field2
Depends on what you want. If you do INNER JOIN, you get the rows that match in Table1 AND Table2. If you do OUTER JOIN, you get all of Table1 and only the matching rows from Table2.
I've used LEFT JOIN and selected the record with NULL id in the Right Table using WHERE clause. See my query and demo below:
SELECT
*
FROM LeftTable A
LEFT JOIN RightTable B ON A.id=B.id
WHERE B.id IS NULL
DEMO HERE
I would use NOT EXISTS operation in that case.
SELECT l.id, l.value
FROM LeftTable l
WHERE NOT EXISTS (SELECT 1 FROM RightTable r WHERE r.id = l.id and r.case_value = l.case_value)
Efficiency comparing and the difference between NOT EXISTS vs. NOT IN vs. LEFT JOIN WHERE IS NULL are here

SQL how to simulate an xor?

I'm wondering if anybody can help me solve this question I got at a job interview. Let's say I have two tables like:
table1 table2
------------ -------------
id | name id | name
------------ -------------
1 | alpha 1 | alpha
3 | charlie 3 | charlie
4 | delta 5 | echo
8 | hotel 7 | golf
9 | india
The question was to write a SQL query that would return all the rows that are in either table1 or table2 but not both, i.e.:
result
------------
id | name
------------
4 | delta
5 | echo
7 | golf
8 | hotel
9 | india
I thought I could do something like a full outer join:
SELECT table1.*, table2.*
FROM table1 FULL OUTER JOIN table2
ON table1.id=table2.id
WHERE table1.id IS NULL or table2.id IS NULL
but that gives me a syntax error on SQL Fiddle (I don't think it supports the FULL OUTER JOIN syntax). Other than that, I can't even figure out a way to just concatenate the rows of the two tables, let alone filtering out rows that appear in both. Can somebody enlighten me and tell me how to do this? Thanks.
Well, you could use UNION instead of OUTER JOIN.
SELECT * FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id
UNION
SELECT * FROM table1 t1
RIGHT JOIN table2 t2 ON t1.id = t2.id
Here's a little trick I know: not equals is the same as XOR, so you could have your WHERE clause something like this:
WHERE ( table1.id IS NULL ) != ( table2.id IS NULL )
select id,name--,COUNT(*)
from(
select id,name from table1
union all
select id,name from table2
) x
group by id,name
having COUNT(*)=1
I'm sure there are lots of solutions, but the first thing that comes to mind for me is to union all the two tables, then group by name, filter with a having clause on the count.
(
SELECT * FROM TABLE1
EXCEPT
SELECT * FROM TABLE2
)
UNION ALL
(
SELECT * FROM TABLE2
EXCEPT
SELECT * FROM TABLE1
)
This should work on most database servers
SELECT id, name
FROM table1
WHERE NOT EXISTS(SELECT NULL FROM table2 WHERE table1.id = table2.id AND table1.name = table2.name)
UNION ALL
SELECT id, name
FROM table2
WHERE NOT EXISTS(SELECT NULL FROM table1 WHERE table1.id = table2.id AND table1.name = table2.name)

Postgresql tables intersect

I have a two tables in my postgresql database.
Both tables have same columns.
How can i prefer values from tableA which are not null?
TableA
id | name
1 | val_a_1
2 | val_a_2
3 | (null)
TableB
id | name
1 | (null)
2 | val_b_2
3 | val_b_3
Result which i want to get:
id | name
1 | val_a_1
2 | val_a_2
3 | val_b_3
For now I've got it like this, but its more complicated, because there are lots of columns.
SELECT *
CASE
WHEN TableA.name is NULL or TableA.name = ''
THEN (SELECT TableB.name FROM TableB where TableB.id = 1)
ELSE TableA.name
END
AS name,
CASE
.
. another columns
.
END
Thanks
why not use COALESCE? Assuming all recordID in tableA is present on Table2
SELECT a.ID,
COALESCE(a.name, b.name) AS "Name"
FROM TableA a
INNER JOIN TableB b
ON a.ID = b.ID
SQLFIddle Demo
Conditional Expressions
The COALESCE function returns the first of its arguments (there can be more arguments) that is not null.
It's all about the COALESCE, not the join itself.
you can use a full outer join for the values which exist in tableA but not in tableB and vice versa:
select coalesce(tableA.ID, tableB.ID) as ID,
coalesce(tableA.Name, tableB.Name) as Name
from tableA full outer join tableB on tableA.ID = tableB.ID

IF condition in INNER JOIN SQL Query

I have a problem in writing sql query. Here is the illustration about my problem.
I have 2 tables in the database as follows :
| Table A | | Table B |
| idTableA | | idTableB |
| idPriority | | idReference |
Those tables above are related. The idReference in Table B is referring to idPriority in Table A. BUT if the value of the idPriority is NULL, then the idReference should be referring to idTableA. Hope you guys get the illustration and can help me working with this problem. Thx in advance.
Double-join method, easy to read
select
B.idTableB,
isnull(A1.idPriority, A2.idTableA) as RefValue
from
TableB as B
left join TableA as A1 on A1.idPriority = B.idReference
left join TableA as A2 on A1.idTableA = B.idReference
Single-join method, two IsNulls()'s:
select
B.idTableB,
isnull(A1.idPriority, A1.idTableA) as RefValue
from
TableB as B
left join TableA as A1 on isnull(A1.idPriority, A1.idTableA) = B.idReference
would the following construct work for you?
select *
from tableA join tableB on (join condition)
where (idpriority is not null)
union
select *
from tableA join tableB on (join condition)
where (idpriority is null)
select *
from tableB b
join tableA a
on
a.idPriority = b.idReference
or
(a.idPriority IS NULL AND b.idReference = a.idTableA)

sql select all but nulls

I want to get values from two tables like in the following example:
Suppose we have this two tables:
TableA (with link to tableB):
Id | Id_TableB | Name
---------------------
1 | 1 | Ralf
2 | NULL | Marta
TableB:
Id | Color
---------------------
1 | Blue
2 | Red
I would like to get values for Color if there is a link, NULL otherwise:
Result:
Id | Name | Color
-----------------------------
1 | Ralf| Blue
2 | Marta| NULL
Any ideas on how to solve this?
You need a left outer join .
SELECT t1.Id, t1.Name, t2.Color
from TableA t1 left outer join TableB t2
on t1.Id_TableB = t2.Id;
Please check the link that I have provided above. Its a simplified tutorial
select
a.Id,
a.Name,
b.Color
from
a
left outer join
b
on
a.Id_TableB = b.Id
group by
b.Id
The group by b.Id is necessary if you have a one-to-many relationship a->b.
You need to use a LEFT OUTER JOIN, which includes rows even when there are NULLs. Something like this:
SELECT *
FROM TableA a
LEFT OUTER JOIN TableB b on a.ID_TableB = b.ID
More info here:
http://msdn.microsoft.com/en-us/library/ms187518.aspx
Hope this helps,
John
just you have to use outer join for this....
select a.id,a.Name, b.Color from tableB as b
left join tableA as a on b.Id = a.id_tableB
and for this you can use in condition as well
you can try below query--
select a.id,a.Name, b.Color from tableB as b,tableA as a on b.Id(+) = a.id_tableB