Oracle SQL: Get all users in one table but not another and join to a third table - sql

I am wondering how to use oracle sql to get all the rows that are in one table but not another. The issue I am having is that the two tables don't have a field in common so I need to join to a third master table.
This is what I've tried which doesn't produce any errors but also produces 0 records which isn't possible but clearly I've done something wrong.
SELECT a.USER_ID, c.AD_ID, c.CREATED_DATE_ FROM $A$ a, $C$ c, $B$ b
WHERE (b.USER_ID IS NULL AND a.CUSTOMER_ID = c.CUSTOMER_ID)
I have three tables:
Table A has fields CUSTOMER_ID & USER_ID
Table B has field USER_ID
Table C has field CUSTOMER_ID
I need all the users that are in table C but not table B. They are all in Table A because that is the master list of users.
Any insight would be greatly appreciated.

SELECT
*
FROM
table_a
WHERE
NOT EXISTS (SELECT * FROM table_b WHERE table_b.user_id = table_a.user_id )
AND EXISTS (SELECT * FROM table_c WHERE table_c.customer_id = table_a.customer_id)

My solution:
select * from TableC tc
join TableA ta on tc.CUSTOMER_ID=ta.CUSTOMER_ID
left join TableB tb on tb.USER_ID=ta.USER_ID
where ta.USER_ID is null

I think you want:
select a.USER_ID, c.AD_ID, c.CREATED_DATE_
from a join
c
on a.customer_id = c.customer_id
where not exists (select 1 from b where b.user_id = a.user_id);

Related

SQL Get rows that doesn't appear in another table

I have this SQL problem: I have tables A and B. Table A has columns id and name, Table B amount and id which is a foreign key to table A.id.
I need to return all table A rows that don't have their id stored in table B. Any ideas?
So the complete opposite is:
SELECT *
FROM a
LEFT OUTER JOIN b ON a.id = b.id;
Here row what I need is left out of result
Just add a where clause:
SELECT a.*
FROM a LEFT OUTER JOIN
b
ON a.id = b.id
WHERE b.id IS NULL;
You can also use NOT EXISTS:
select a.*
from a
where not exists (select 1 from b where b.id = a.id);
In most databases, the two methods typically have similar performance.

SQL: Join table a and b then join table c to get the results that are on a but not on c?

i have 3 tables. Table a pk = userid, table b and c fk = userid. On table b RoleID column is equal to Usermanager column from table c but w a new value.
So i joined table a and b with below query
select a.Username, a.Userid, b.Roleid
from NewTable a
join RoleTable b
on a.UserID=b.UserID
where b.RoleID = 2
This results in 502 records.
Table c query is
select *
from OldTable
where UserManager = 1
and Authorized = 1
and Status = 'A'
This results in 500 records.
So I'm trying to join the 2 queries to find the 2 records that are not on table c but are only on table a.
Thanks.
Try this:
select a.Username, a.Userid, b.Roleid
from NewTable a
join RoleTable b
on a.UserID=b.UserID
where
b.RoleID = 2
AND
NOT EXISTS
(select *
from OldTable AS c
where c.UserManager = 1
and
c.Authorized = 1
and
c.Status = 'A'
AND
a.userid = c.userid)
I used the two queries you mentioned you were using and just made the table c query into a WHERE NOT EXISTS subquery. It should provide those 2 results you are looking for.
Something like this should do the trick. You can work out the details for your database.
select fields
from tableA join tableB on something
where whatever
and tableA.someField in
(select someField
from tableA join tableB on something
where whatever
except
select someEquivalentField
from tableC)
The two where whatevers should be the same.
If I understand your question correctly... the following will join Table A and Table C and then find those that dont have corresponding values in Table C
Select * from Table A A
LEFT JOIN Table C C On A.UserId = C.UserId
Where C.UserId is NULL
This is the basic concept.. you need to work on it to get the syntax to fit your motives
You can do this with a Left Join
select subA.*
from (
select a.Username, a.Userid, b.Roleid
from NewTable a
join RoleTable b
on a.UserID=b.UserID
where b.RoleID = 2
) subA
left join (
select userID
from OldTable
where UserManager = 1
and Authorized = 1
and Status = 'A'
) subB
on subA.Userid = subB.UserID
Where subB.userid is null

SQL Query Duplicating records

I've got two tables.
Let's call them table_A and table_B.
Table_B contains the ForeignKey of table_A.
Table_A
ID Name
1 A
2 B
3 C
Table_B
ID table_a_fk
1 2
2 3
Now I want to get all the names out of table_a IF table_b does not contain the ID of the record in table_a.
I've tried it with this query:
SELECT a.name
FROM table_a a, table_b b
WHERE a.id != b.table_a_fk
With this Query I'm getting the right result I just get this result like 5times and I don't know why.
Hope someone can explain me that.
Your query creates a cartesian product between your two tables A and B. It is the cartesian product that generates those duplicate values. Instead, you want to use an anti-join, which is most commonly written in SQL using NOT EXISTS
SELECT a.name
FROM table_a a
WHERE NOT EXISTS (
SELECT *
FROM table_b b
WHERE a.id = b.table_a_fk
)
Another way to express an anti-join with NOT IN (only if table_b.table_a_fk is NOT NULL):
SELECT a.name
FROM table_a a
WHERE a.id NOT IN (
SELECT b.table_a_fk
FROM table_b b
)
Another, less common way to express an anti-join:
SELECT a.name
FROM table_a a
LEFT OUTER JOIN table_b b ON a.id = b.table_a_fk
WHERE b.id IS NULL
use distinct
SELECT distinct a.name
FROM table_a a, table_b b
WHERE a.id != b.table_a_fk
or better is...
Select distinct name
from tableA a
Where not exists (Select * from tableB
Where table_a_fk = a.id)

The Difference Inner Join Query

I'm just curious, if i have table a and table b.
I write query 1:
SELECT * FROM table a INNER JOIN table b ON table a.id = table b.id
I write query 2:
SELECT * FROM table b INNER JOIN table a ON table b.id = table a. id
What is the difference both of above query?
Thank you
When using INNER JOIN , there is no difference in resultset returned except in order of columns when SELECT * is used i.e. columns are not explicitly mentioned.
SELECT *
FROM table a
INNER JOIN table b
ON table a.id = table b.id
returns columns from tableA followed by columns from tableB
SELECT *
FROM table b
INNER JOIN table a
ON table b.id = table a. id
returns columns from tableB followed by columns from tableA
The second table matches data with the first one.
So it is better to put smaller table on the second place.

Join and showing different columns from tables

I have a simple SQL question, I thought it would be quite straight forward but have got myself in a muddle. Any help would be appreciated
I have table A which contains a last updated
Table A has a one to many with Table B
Table B has a one to many with Table C
I want to show all rows of table C with the last updated time from table A. I have tried some joins but they dont seem to be quite working. Ideally I want somehting like
select a.lastUpdated c.* from TableA a, TableC c where
a.id in (select a_id from TableB where (select b_id from TableC where c_id = select
id from TableC where XXXX=YYYY))
so I can pass in an id for table C and then get one row returned with the last updated time present.
XXX=YYY would be my criteria for returning one row of table C.
Any help or pointers appreciated
Thanks
Something like
SELECT c.*
FROM TableA AS a
INNER JOIN TableB AS b
ON a.a_id = b.b_id
INNER JOIN TableC AS c
ON b.b_id = c.c_id
WHERE a.lastUpdated = c.lastUpdated;
Should work. This is a situation where a striaght INNER JOIN should suffice; unless of course I have missed something.
I hope this helps.
You should be able to do this by joining A and B together, aggregating the results at the c_id level, and then joining in C:
select tc.*, maxlastupdated
from tablec tc left outer join
(select tb.c_id, max(lastupdated) as maxlastupdated
from tablea ta join
tableb tb
on ta.b_id = tb.b_id
group by ta.id
) ta
on tc.c_id = ta.c_id
You need to drive your SQL query from Table C.
The query below displays the updated timestamp column from table A.
Since it is a one-to-many in the direction of tables A --> B --> C
You will inevitably end-up with a lot of rows in table C - all with the same timestamp.
SELECT c.*, a1.update_timestamp
FROM table_c c, table_b b, table_a a1
WHERE c.join_column = b.join_column
AND b.join_column = a1.join_column
AND a1.update_timestamp =
(SELECT max(a2.update_timestamp) FROM table_a a2
WHERE a2.<identifying columns> = a1.<identifying columns>
);