Rows that are in table A but not in B - sql

How can I check the rows for columns a, b, c, and d in table A but not in table B?

select a.a,a.b,a.c,a.d
from tablea as a
except
select b.a,b.b,b.c,b.d
from tableb as b

If you want to get full rows from table a you can use exists:
select *
from tbl_a
where not exists (
select *
from tbl_b
where tbl_b.a = tbl_a.a
and tbl_b.b = tbl_a.b
and tbl_b.c = tbl_a.c
and tbl_b.d = tbl_a.d
)

You can LEFT JOIN the table B to get the common elements between both tables plus the remaining in A (if any field doesn't match the join, B will be NULL), and then remove the inner part by filtering only the NULL values for B
SELECT A.*
FROM A
LEFT JOIN B
ON A.a = B.a
AND A.b = B.b
AND A.c = B.c
WHERE COALESCE(B.a, B.b, B.c) IS NULL;
fiddle

How can I check the rows for columns a, b, c, and d in table A but not in table B?
This will show you the total values for all the columns you indicated in A as well as row data
SELECT
a.a
,a.b
,a.c
,a.d
,b.e
FROM A as a
LEFT JOIN B as b
ON a.a = a.b
Where b.a IS NULL
and b.b IS NULL
and b.c IS NULL
and b.d IS NULL
GROUP BY GROUPING SETS ((),(a.a,a.b,a.c,a.d))
ORDER BY a.a

Related

Is there a way to look up only different values in the existing table and in the change history table in the Oracle database?

I'm using A table and A_Hist table.
The columns in table A are id(PK), a, b, c, d ...
The columns in table A_Hist are id, timestamp, a, b, c, d ...
Table A_Hist uses (id, timestamp) as PK
Both tables are the same except for the timestamp column.
Is there a way to look up only different values for each column in the data of the two tables?
If you aren't interested in timestamp (as you can't compare it anyway; it doesn't exist in A), then you could
select id, a, b, c, d from a
minus
select id, a, b, c, d from a_hist
which would return all rows in A that don't exist in A_HIST. Apply the opposite, if needed.
Or, you could join tables on ID column and search for differences:
select a.id, a.a, b.a,
a.b, b.b,
a.c, b.c
a.d, b.d
from a join a_hist b on a.id = b.id
where a.a <> b.a
or a.b <> b.b
or a.c <> b.c
or a.d <> b.d
If NULLs are allowed, use the NVL function, e.g. where nvl(a.a, 'x') <> nvl(b.a, 'x').

SQL join on equal plus cartesian of those which not equal

I need to join two tables in such way that in the output I have an UNION of:
INNER JOIN of matching records
CARTESIAN of those which does not match (excluding the records above, i.e. those that match)
Maybe this looks like a piece of cake, but I need to do it in an efficient way (for far more complex query than this below).
a: 1|2|3|5
b: 2|3|4|6
result: (2,2)|(3,3)|(1,4)|(1,6)|(5,4)|(5,6)
Any helpful tricks you could advise? (I work on SQL Server 2012)
Thanks!
I'd use a CTE to define the joined records, something like this:
WITH MatchedRows
AS
SELECT A.a, B.b FROM A a INNER JOIN B b ON A.a = B.b
SELECT MatchedRows.a, MatchedRows.b
FROM MatchedRows
UNION
SELECT A.a, B.b FROM A a, B b
WHERE A.a NOT IN (SELECT a FROM MatchedRows)
AND B.b NOT IN (SELECT b FROM MatchedRows)
You didn't say what the column names were, so just called them Col.
SELECT A.Col,
B.Col
FROM A
INNER JOIN B
on A.Col = B.Col
UNION ALL
SELECT A.Col,
B.Col
FROM A
CROSS JOIN B
WHERE A.Col NOT IN (SELECT B.Col FROM B)
AND B.Col NOT IN (SELECT A.Col FROM A)

Run a query on Parent to show records of only one child table

I've 3 tables, viz A, B & c.
B & C has forign key of A.
Now I want to run a query on A, in such a way, that only records of B are returned.
That is, I want to exclude all the results of C and show only results of B, when a query is executed on all the records of A.
Hope, I've the question makes sense.
If you want to return all records of A and any matching records from B then something a left outer join is appropriate:
SELECT a.*, b.*
FROM a, b
WHERE a.id = b.id
This will return each record from A and populate values from B where there is a match. This will also return multiple rows for records that occur in A if there are multiple rows in B that match.
Just because there is a foreign key in C that references something in table A, it won't be returned unless you use it in your query.
If you just want to return all records from B when the foreign key appears in A then maybe you want:
SELECT *
FROM B
WHERE B.id in (SELECT id FROM A)
AND B.id not in (SELECT id FROM C)
or
SELECT *
FROM B
WHERE EXISTS (SELECT 1 FROM A JOIN B on A.id = B.id)
AND NOT EXISTS (SELECT 1 FROM C JOIN B on C.id = B.id)
All these assume that id is the key which is common.
Is this what you want?
select a.*
from a
where exists (select 1 from b where b.aid = a.aid) and
not exists (select 1 from c where c.aid = c.aid);

Condition between two join in SQL

I have 3 tables and i want to join two of them with a condition.
For exemple if i have table A, table B and Table C, i'd like to have JOIN AB or JOIN BC.
Does something like this exists ?
SELECT *
FROM B
(JOIN A
ON (B.b=A.id_a)
OR (B.b=A.id_b))
OR
(JOIN C
ON (B.b=C.id_a)
OR (B.b=C.id_b))
WHERE B.a=1001485422
You can do both joins at once
select *
from
b
left join
a on b.b in (a.id_a, a.id_b)
left join
c on b.b in (c.id_a, c.id_b)
where b.a = 1001485422

Union ALL multiple query Google BigQuery

I have three queries with the same column count and structure, does Google BigQuery support union all? I know it supports union but I need it to merge the result of the query into one result.
I have tried:
SELECT *
FROM
(SELECT a.a AS a, a.b AS b, d.c AS c FROM table_a a JOIN table_d d on d.a = a.a),
(SELECT c.a AS a, c.b AS b, d.c AS c FROM table_c c JOIN table_d d on d.a = ca.a),
(SELECT b.a AS a, b.b AS b, d.c AS c FROM table_b b JOIN table_d d on d.a = b.a)
I get the following error:
Union results in ambiguous schema [d.c] is ambiguous and is aliasing multiple fields
Thanks For your help.
Must you know if the data are come from table a, b or c? If you don't need to know, you can try the following query:
select *
from
(select a, b
from table_a, table_b, table_c) as a
join
(select a, c
from table_d) as d
on a.a = d.a