Selecting from three tables, distinct selections from one - sql

I have three tables, I'll call them table A, B and C here. Table A has a one to many relation to B and B has a one to many relation with C. For this query, I only want disctinct values from C, but the query below will give me multpile C records that match B.
Right now my query is as such:
Select * from A Left Outer Join B on A.key = B.key Left Outer Join C on B.AltKey = C.AltKey
Any ideas?
Many thanks in advance.

Why are you using LEFT OUTER JOIN? Try switching that with plain old JOIN and see if you get what you're looking for.

Select distinct C.* from C
Left Outer Join B on C.a = B.a
Left Outer Join A on B.a = A.a

Related

Getting a field from a table that is not in the left outer join in the same query

I have 4 tables, 3 of which are joined, but I need to get a field from the forth table (Table_D). For the sake of simplicity lets say they are Tables A, B, C, D.
Select Distinct A.Field_1, B.Field_2, C.Field_3
From Table_A
Left outer join B on A.Field_z= B.Field_z
Left Outer Join C on A.Field_z= C.Field_z
where A.Field_z in (1111);
This seems to work but I need a field in Table_D that is only connected to Table_A through Table_C.
How can I add it to the join? or can I?
Thanks!
WB
The on clause has essentially all the features of the where clause. on clauses for any part of the join can refer to any attribute of any entity in the from clause, I suspect your confusion comes from thinking that you can only join subsequent entities to the first entity in the from clause. If Table_D is related to Table_A through Table_C, you might see a from/join/on construct like:
select a.thing, b.things, c.thang, d.stuff
from Table_A a
left join Table_B b
on a.id = b.a_id
left join Table_C c
on a.id = c.a_id
left join Table D d
on d.id = c.d_id
where
a.this = b.that
Note that the word "outer" is implied in a left join, and is not necessary for syntactic completion.
Of course you can add it. You don't specify the logic, but something like this:
Select Distinct A.Field_1, B.Field_2, C.Field_3, D.??
From Table_A a Left outer join
B
on A.Field_z= B.Field_z Left Outer Join
C
on A.Field_z= C.Field_z Left Outer Join
D
on . . .
where A.Field_z in (1111);
Just fill in the conditions that you want. You want a left join, because the condition between c and d would otherwise turn the outer join to c into an inner join.
If I understand you correctly, I believe this would work:
Left Outer Join D on C.Field_z= D.Field_z
You can try this way. It will help i guess
Select Distinct A.Field_1, B.Field_2, C.Field_3, c.Field_4
From Table_A
Left outer join B on A.Field_z= B.Field_z
Left Outer Join ( select C.field_3, d.Field_4, c.Field_z from c inner join d on c.field_z = d.field_z ) c on A.Field_z= C.Field_z
where A.Field_z in (1111);

left join with three tables

Can anyone explain what will happen in following scenario?
SELECT *
FROM A,
B
LEFT JOIN C
ON B.FIELD1=C.FIELD1
WHERE A.FIELD1='SOME VALUE'
Here table A and table B are not joined with any condition. So my doubt is what kind of join will be applied between A and B?
A cross join (cartesian product, if you prefer) will be applied between the results of A and B left join C: each row in the first set will be tied to each row in the second set.
A cross join applies, If you don't used a join condition, get irrelavent results also.
Please try it
SELECT * FROM A INNER JOIN B ON A.IDCOLUMND=B.IDCOLUMN LEFT JOIN C ON B.FIELD1=C.FIELD1

PL/SQL Using multiple left join

SELECT * FROM Table A LEFT JOIN TABLE B LEFT JOIN TABLE C
From the snippet above, TABLE C will left join into (TABLE B) or (data from TABLE A LEFT JOIN TABLE B) or (TABLE A)?
TABLE C will left join into 1. (TABLE B) or 2. (data from TABLE A LEFT JOIN
TABLE B) or 3. (TABLE A)?
The second. But The join condition will help you to understand more.
You can write:
SELECT *
FROM Table A
LEFT JOIN TABLE B ON (A.id = B.id)
LEFT JOIN TABLE C ON (A.ID = C.ID)
But you are able to:
SELECT *
FROM Table A
LEFT JOIN TABLE B ON (A.id = B.id)
LEFT JOIN TABLE C ON (A.id = C.id and B.code = C.code)
So, you can join on every field from previous tables and you join on "the result" (though the engine may choose its way to get the result) of the previous joins.
Think at left join as non-commutative operation (A left join B is not the same as B left join A) So, the order is important and C will be left joined at the previous joined tables.
The Oracle documentation is quite specific about how the joins are processed:
To execute a join of three or more tables, Oracle first joins two of
the tables based on the join conditions comparing their columns and
then joins the result to another table based on join conditions
containing columns of the joined tables and the new table. Oracle
continues this process until all tables are joined into the result.
This is the logic approach to handling the joins and is consistent with the ANSI standard (in other words, all database engines process the joins in order).
However, when the query is actually executed, the optimizer may choose to run the joins in a different order. The result needs to be logically the same as processing the joins in the order given in the query.
Also, the join conditions may cause some unexpected conditions to arise. So if you have:
from A left outer join
B
on A.id = B.id left outer join
C
on B.id = C.id
Then, you might have the condition where A and C each have a row with a particular id, but B does not. With this formulation, you will not see the row in C because it is joining to NULL. So, be careful with join conditions on left outer join, particularly when joining to a table other than the first table in the chain.
You need to mentioned the column name properly in order to run the query. Let´s say if you are using:
SELECT *
FROM Table A
LEFT JOIN TABLE B ON (A.id = B.id)
LEFT JOIN TABLE C ON (A.id = C.id and B.code = C.code)
Then you may get the following error:
ORA-00933:SQL command not properly ended.
So to avoid it you can try:
SELECT A.id as "Id_from_A", B.code as "Code_from_B"
FROM Table A
LEFT JOIN TABLE B ON (A.id = B.id)
LEFT JOIN TABLE C ON (A.id = C.id and B.code = C.code)
Thanks

Do I have to do a LEFT JOIN after a RIGHT JOIN?

Say I have three tables in SQL server 2008 R2
SELECT a.*, b.*, c.*
FROM
Table_A a
RIGHT JOIN Table_B b ON a.id = b.id
LEFT JOIN Table_C c ON b.id = c.id
or
SELECT a.*, b.*, c.*
FROM
Table_A a
RIGHT JOIN Table_B b ON a.id = b.id
JOIN Table_C c ON b.id = c.id
also, does it matter if I use b.id or a.id on joining c?
i.e. instead of JOIN Table_C c ON b.id = c.id, use JOIN Table_C c ON a.id = c.id
Thank you!
If it doesn't change the semantics of the query, the database server can reorder the joins to run in whichever way it thinks is more efficient.
Usually, if you want to force a certain order, you can use inline view subqueries, as in
SELECT a.*, x.*
FROM
Table_A a
RIGHT JOIN
(
SELECT *, b.id as id2 FROM Table_B b
LEFT JOIN Table_C c ON b.id = c.id
) x
ON a.id = x.id2
According to the definitions:
JOIN
: Return rows when there is at least one match in both tables
LEFT JOIN Return all rows from the left table, even if there are no matches in the right table
RIGHT JOIN Return all rows from the right table, even if there are no matches in the left table
The first option would include all raws from the 1st Join on Tables a and b even if there are no matching ones in table c, while the second statement would show only raws which match ones in table c.
regarding the second question i guess it would make a difference, since the 1st join includes all ids from table b, even though there are no matching ones in table a, so once you change your Join creterium to a.id you will get a different set of ids than b.id.
Yes, you do need a LEFT JOIN after a RIGHT JOIN
See
http://sqlfiddle.com/#!3/2c079/5/0
http://sqlfiddle.com/#!3/2c079/6/0
If you don't, the (inner) JOIN at the end will cancel out the effect of your RIGHT JOIN.
That wouldn't make any sense to have a RIGHT JOIN if you don't care. And if you care, you will have to add a LEFT JOIN after it.

Inner joining one table against many others

I have a table A with columns (Id,Value)
and a table B with Columns (BId,Id,..)
and a table C with columns (CId,Id,...)
I need to perform an inner join on these tables as follows
select a.Id,a.Value from A a
inner join B b on b.Id=a.Id
inner join C c on c.Id=a.Id
where <many conditions on table B and C>
How can i achieve the same. Now when i just run the query
select a.Id,a.Value from A a
inner join B b on b.Id=a.Id
inner join C c on c.Id=a.Id
it doesnt return anything.. please help.
FYI when i run the joins separately it gives me the rows. I just want a union of them...
Sample data:
A
1
2
3
B
2
C
3
then i want to select
A
2
3
Thanks in advance.
So, following your comments, it appears that you want something like this:
select a.Id,a.Value from A a
inner join B b on b.Id=a.Id
where <many conditions on table B>
UNION ALL
SELECT a.Id, a.Value from A
inner join C c on c.Id=a.Id
where <many conditions on table C>
As long as the fields match on ID from A -> B and A -> C and you dont have any other join condition, you should be able to see the matching rows.
I could not understand your point about how the B and C Id do not match. if a.id=b.id and a.id=c.id, Doesn't it automatically imply b.id = c.id?
Anyways, in situations like these, I try to do outer join of A on B and C and see if the rows that I think are matching in fact do exist.
select a.Id,a.Value from A a
left outer join B b on b.Id=a.Id
left outer join C c on c.Id=a.Id
where (b.id is not null or c.id is not null)
/* Matching record found in b or c */
EDIT: Based on your requirement, you can use the approach that Lamak suggested above (Using UNION Alls) or if you are certain that for each record in A, you will only have one record in B and one in C at most and only one column, you can use the scalar sub query approach.