How to create a query that returns only records in one table without a foreign key - sql

How do I create a query that returns only records in one table that have no foreign key relations with a particular attribute? I'm not even sure how to properly formulate the question, so I'm giving an example below:
I have Table B. It has an ID and other stuff that's not important.
I have Table C. It has an ID, an attribute (call it Available) which is only ever 'Yes' or 'No'.
Each record in Table B may have zero or more records in Table C related to it. They are connected by Table BC_Line, where each record has a FK for B_ID and a FK for C_ID. Hence, if records C_ID=1 and C_ID=2 are related to B_ID=1, then BC_Line has two records: (B_ID_FK=1 C_ID_FK=1) and (B_ID_FK=1 C_ID_FK=2).
I want a query that returns ONLY records in B that have NO associated records in C with C_Available='No'. A record in B might have several related records in C, all with 'Yes', and that would be shown. A record in B might have several related records in C all with 'No', that would NOT be shown. A record in B might also have records in C, some 'Yes' and some 'No', but that record would still not be shown. All related C records must be 'Yes'.
I'm not sure how to do it. I understand how to create queries and how to do Joins, but I do not know how to combine them in such a way as to get what I want. It's possible this is a well known problem, but I haven't been able to find the answer, partly because I have difficulty articulating my problem.
For the record, I am using Oracle.

You could use EXISTS:
SELECT *
FROM TableB b
WHERE NOT EXISTS (SELECT 1
FROM TableC c
WHERE c.C_Available='No'
AND b.B_ID_FK =c.C_ID);
Note! I've assumed that c.C_Available is defined as NOT NULL and it could hold only Yes/No values.

You could also use the left join method.
select b.*
from tableB b left join bc_line on b.b_id = bc.b_id
left join tableC c on bc.c_id = c.c_id
and c.c_available = 'No'
where c.c_id is null

Related

Returning two pieces of data from a tables based on a two different joins

I'm sure there is an answer out there for this, I am just having a hard time explaining what exactly it is I am looking for making it really hard to research:
I basically have 2 tables:
Table A:
PrimaryKeyID
SalesmanID
ManagerID
Table B:
List of all employers with ID being the primary key (auto incremented from 1)
I need to get both the Salesman and Manager Names from Table B, from a specific row in table A. Consider Table A like a transaction log.
Just a way to do it
SELECT A.ID, SalesMan.NAME, Manager.NAME
FROM TableA A
LEFT JOIN TableB SalesMan ON SalesMan.Id= A.SalesmanID
LEFT JOIN TableB Manager ON Manager.Id= A.ManagerID
WHERE (A.Your condition here)
AND (SalesMan.SalesmanID IS NOT NULL OR Manager.ManagerID IS NOT NULL)

View new count column

I have 2 tables. One who is like a transactional table
userId category
Second table also has
userId (as primary key)
and other columns (not important)
I wanted to create a view based on these 2 tables. Also, I want to have one column which puts into the cells the count from the transactional table who has the same id and eventually matches a special categorie f.e "car".
I thought of maybe using nested select statement, but since i'm a beginner i'm a little bit confused.
Try something like this.
select count(b.userId) as ID, b.category from table2 a inner join transactional b
on a.userId = b.userId where b.category= 'car' group by b.category;

Joining two tables to update results in third table using like

I am trying to join two tables and update the results in the third table.
So table A is the results table and it has the columns customer number and score.
Table B has customer number and ind_code and table C has ind_code and ind_score.
So the output of the query should be such that the ind_code in table B and C should join together based on the first two digits and ind_score should be updated in Table A in the score column. Table A and Table B should be joined on the basis of customer number.
Could anyone please help. I tried multiple queries but nothing seems to work. i am using oracle sql developer
Generally, the JOIN operation mustn't cut field information but if your structure (for me not correct) is that ...
If I understand better:
UPDATE TableA
SET score =
(SELECT MAX(C.ind_score)
FROM TableC C
JOIN TableB B
ON C.ind_code = SUBSTRING(B.ind_code, 1, 2)
WHERE B.customernumber = TableA.customernumber)
I use on subquery MAX aggregate function, because I don't know if your cut of ind_code of TableB can be not unique (i.e. you have ind_code 5555 and 5554)

How to know the number difference between 2 tables in sql

I really need to know the query to display another field which is I want to name it as "number_difference" between 2 tables that required a numeric (in this case as a quantity).
I have 2 tables that totally same, let say, I modify the value from table A so some value in table A different with table B. And I want to join it into 1 table that display rows that some values were modified. I already get the result by this query :
**
select a.T1, a.T2 a.T3 ... from A where not exists (select * from B
where a.T1=b.T1 and a.T2=b.T2 and a.T3=b.T3)
**
This query works well. But, I want to add more field, the difference number between this 2 field (quantity) in 2 different tables. So let say, a.T3 and b.T3 are quantities. And want to display it as "number_difference" next to field (T2) which I display. Sorry I can't post images, they say I need at least 10 reputation to post. Please help me master, how can I make it everytime I use join/inner join it always display soo many rows that I only need the rows which a value from 1 table I have modified.
Thanks in advance.
You can get something like this
Select * From A Where A.id not in( Select Id from B)
or
Select A.* From A left join B on A.id = B.id Where A.id <> B.id
If you are specifically targeting a situation with two identical tables, where one underwent UPDATE operations only (no INSERT), and you want to identify those records which were modified, then:
select a.* from a, b where a.id=b.id and ( a.c1!=b.c1 or a.c2!=b.c2)

Joining, but not joining (hypothetical q.)

Lets suppose that I have a table A with couple of columns. I work with tables, where there is no index on the entries, since they are 'historical' tables. I use one specific column, though, to sort of identify my things. Lets call this ID.
If you'd make a query like the one below, sometimes you'd get one line back, other cases a few.
SELECT * FROM A WHERE ID = '<something>'
Lets say I have two more tables, B and C. Both have ID columns, like A.
Also, some of the IDs in A, are also in B OR C. IDs existing in B CANNOT exist in C. And ALL IDs in A EXIST in either B OR C.
B and C contain extra information, which I'd like to join to A at the same SELECT.
My problem is, that they would only provide extra information. I do not want extra lines in my output..
To make it more clear: my selection from A returns a hundred lines of output.
When I left/right/inner join B table, I —probably— will have less lines as output. Same thing with joining C.
AND FINALLY, my question is:
Is there a way to join table B only on those IDs, which exist in B and vice versa? (And it I would want it in the same SELECT.... statement.)
If you don't want extra lines in your output, you could do something like this:
select *
from A join
(select B.*
from B
group by B.id
) B
on A.id = B.id;
This would choose arbitrary values from B for each id and join them back to A. Is this what you want?
Well it seems like you should build some left join between A and two "Select MAX"s: one from table B, the other one from table C.
And if you do not want 'duplicate' IDs from table A, a 'group by' on table A should help.