Joining, but not joining (hypothetical q.) - sql

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.

Related

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

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

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)

Trying to design a summary table in SQL using multiple others

Very new to SQL programming so apologies if my terminology is a little off.
I need some help combining a few tables, however I'm worried that it's not even possible!! (but what do I know)
So I have 1 table that is just a list of feeds. A, B, C, D etc (15 rows in total) and each feed has other information attached to it such as Full name, location etc etc. I am only interested in the Feed column.
Each feed then has a corresponding data table which contains a list of records. Eg Feed A data is contained in TableA, Feed B data is contains in TableB and so on.
Basically what I need is a combined table that shows the list of Feeds in the 1st Column ( So A, B, C, D…..) and then a second column which counts the records from each separate data table corresponding to that feed.
So the end result would look something like this:
Feed No of Records
A 4 (from TableA)
B 7 (from TableB)
C 8 (from TableC)
D 1 (from TableD)
Possible?
Any help on sql code would be much appreciated.
Thanks

SQL mapping between multiple tables

This is a SQL design question. First, the setup. I have three tables:
A, which is automatically populated based on a query against a linked server. The data in this table cannot be changed;
B, which has just a dozen or so rows, containing the names for collections of As;
AtoB, which is the mapping table by which As are organized into named collections, with foreign keys on both columns;
For example, A contains:
Giraffe
Owl
Tiger
And B contains:
Seattle Zoo
San Jose Zoo
And AtoB contains:
1,1 (Giraffe in Seattle)
2,1 (Owl in Seattle)
3,1 (Tiger in Seattle)
2,2 (Owl in San Jose)
Now, the problem:
I've been asked to include in some of these collections items not found in A. So, I create a table, C, with the same identity and Name columns as A, and populate it. In keeping with the earlier example, let's say C contains:
Dragon
The question is, how do I include items from C in AtoB? What if I need to include a Dragon in the Seattle Zoo?
My first instinct, being naive, was to create a view V containing the union of A and C, and modifying AtoB to be VtoB. That's where my naivety paid off: one cannot create a foreign key to a view.
I suspect that there's a standard, correct means of relating one or more A OR C with a B.
To expand on Arthur Thomas's solution here's a union without the WHERE in the subselects so that you can create a universal view:
SELECT A.Name as Animal, B.Name as Zoo FROM A, AtoB, B
WHERE AtoB.A_ID = A.ID && B.ID = AtoB.B_ID
UNION
SELECT C.Name as Animal, B.Name as Zoo FROM C, CtoB, B
WHERE CtoB.C_ID = C.ID && B.ID = CtoB.B_ID
Then, you can perform a query like:
SELECT Animal FROM zoo_animals WHERE Zoo="Seattle Zoo"
If you can't put a Dragon in A then you will need to create another table and another link table. The problem is creating a unique set of data that needs to be stored (another table) that cannot be the same set as A. Since it isn't the same set then you can no longer use the link table (AtoB) which has foreign keys that ensure that the link is a reference from set A. So you could create a tables like this:
imaginary_creatures
id
name
imaginary_creatures_to_b
imaginary_creatures_id (link to imaginary_creatures table)
b_id (link to zoos table)
Later when you want to get all creatures in a zoo you can do a UNION
SELECT A.Name FROM A where A.ID IN
(SELECT AB.A_ID FROM AtoB AB WHERE B_ID =
(SELECT B.ID FROM B WHERE B.Name = 'Zoo Name'))
UNION
SELECT i.name FROM imaginary_creatures i i.id IN
(SELECT ic.imaginary_creatures_id FROM imaginary_creatures_to_c ic
WHERE ic.b_id = (SELECT B.ID FROM B WHERE B.Name = 'Zoo Name'))
There may be a better way of writing that, but it should work for your purposes.
Arthur Thomas has a good solution, the other possible solution is to add a column to the link table indicating which table (A or C) it is related to. Then enforce the relationships through triggers rather than foreign keys. But really Arthur's solution is the preferred way of doing this sort of thing.
What you want to do is put Dragon in A, and if you want to select ALL records from A regardless of if they have a matching record in AtoB, do a LEFT OUTER JOIN. Something like this:
SELECT * FROM A
LEFT OUTER JOIN AtoB
ON A.id = AtoB.A_ID
Edit: This would only work if you could add your new records to A. I missed the fact that you are not able to. I think Arthur Thomas's solution is what you want.
Truncate the table dept_details
Display the structure of the table emp_details
Convert the first letter of emp_name into capitals.