Assuming I have these two tables like:
Table: tab1
| valA | valB | valC | valD |
|---|---|---|---|
| 1 | 11 | 111 | A |
| 2 | 11 | 333 | A |
| 3 | 44 | 444 | B |
| 3 | 66 | 666 | D |
Table: tab2
| val1 | val2 | val3 | val4 |
|---|---|---|---|
| 1 | 11 | 111 | A |
| 1 | 22 | 222 | A |
| 2 | 44 | 333 | B |
| 3 | 55 | 555 | A |
| 3 | 66 | 666 | D |
I have 3 cases that I have unite with UNION. This is the code:
WITH tog AS ( SELECT* FROM tab1 INNER JOIN tab2 ON ValA = Val1 AND ValB = Val2 UNION SELECT* FROM tab1 INNER JOIN tab2 ON ValA = Val1 AND ValB <> Val2 AND ValD = Val4 UNION SELECT* FROM tab1 INNER JOIN tab2 ON ValA = Val1 AND ValC = Val3 AND ValD <> Val4 )
The result would be:
table: tog
| valA | valB | valC | valD | val1 | val2 | val3 | val4 |
|---|---|---|---|---|---|---|---|
| 1 | 11 | 111 | A | 1 | 11 | 111 | A |
| 1 | 11 | 111 | A | 1 | 22 | 222 | A |
| 2 | 33 | 333 | a | 2 | 44 | 444 | B |
| 3 | 66 | 666 | D | 3 | 66 | 666 | D |
So, I need the table of tab1 but without the matches, like:
| valA | valB | valC | valD | val1 | val2 | val3 | val4 |
|---|---|---|---|---|---|---|---|
| 3 | 44 | 444 | B |
I tried something like this, but I know this is totaly wrong:
SELECT * FROM tab1 LEFT JOIN tog ON tab1.valA = tog.val1 WHERE tog.val1 IS NULL
I am pretty new on SQL so I would appreciate any tipps and suggestions.
Advertisement
Answer
You want to select data from tab1 where not exists a match in tab2.
select *
from tab1
where not exists
(
select null
from tab2
where tab1.vala = tab2.val1
and
(
(tab1.valb = tab2.val2) or
(tab1.vald = tab2.val4 and tab1.valb <> tab2.val2) or
(tab1.valc = tab2.val3 and tab1.vald <> tab2.val4)
)
);
Or, if you need the empty tab2 columns:
select *
from tab1
left outer join tab2
on tab1.vala = tab2.val1
and
(
(tab1.valb = tab2.val2) or
(tab1.vald = tab2.val4 and tab1.valb <> tab2.val2) or
(tab1.valc = tab2.val3 and tab1.vald <> tab2.val4)
)
)
where tab2.val1 is null; -- dismiss the matches