Oracle join 2 tables on same column - sql

Can someone explain to me why the below query is returning null in the description field
Table A:
OCD CCD
A B
C D
E F
Table B:
CD DESCRIP
A AL
B BL
C CL
D DL
E EL
F FL
Result:
OCD DESCRIP CCD DESCRIP
A AL B BL
C CL D DL
E EL F FL
Incorrect Query:although this query runs correctly. It doesn't give description values.
select a.ocd,b.DESCRIP,a.CCD,b.DESCRIP
from A a, B b
where a.ocd=b.cd(+)
and a.ccd=b.cd(+);
Correct query
select a.ocd,b.DESCRIP,a.CCD,b.DESCRIP
from A a, B b1, B b2
where a.ocd=b1.cd(+)
and a.ccd=b2.cd(+);

You need to look up the values twice because you have two codes. This requires two joins, which should be left joins if there is a possibility of non-matches:
select a.ocd, b1.DESCRIP, a.CCD, b2.DESCRIP
from A left join
B b1
on a.ocd = b1.cd left join
B b2
on a.ccd = b2.cd;
The conditions in your first query are:
where a.ocd=b.cd(+) and a.ccd=b.cd(+);
Just look at them. They imply that in any matching row, a.ocd = a.ccd, and that is not true on any rows in your data. Hence, there is no match and the result is NULL.
Also, learn to use proper explicit JOIN syntax. Explicit joins are more powerful, more portable, and easier to read. Further, Oracle deprecated the (+) syntax many years ago, meaning that even Oracle may not support it in the future.

From what you call the "correct query" it seems you want to select each row from table A, and then for each value in that row, the corresponding value in a row in Table B. In the first query, where you join table A and table B, the join condition requires that both values from the row in table A are matched IN THE SAME ROW in table B. Clearly that doesn't meet your specification. If you want to match one row from table A with two (usually DIFFERENT) rows from table B, you need to join table A with table B twice, as in the correct query.
When you join two tables, all the combinations of ONE ROW from the first table and ONE ROW from the second table are checked to see if the join condition(s) is/are met. When you join three tables, all the combinations of ONE ROW from each of the three tables are checked against the join condition(s). This is why you need table B twice in your join: you want to combine one row from table A and TWO rows from table B for one row in the result.

You should translate your query to standard SQL:
select a.ocd, b.DESCRIPT, a.CCD, b.DESCRIPT
from a
left join b on a.ocd = b.cd and a.ccd = b.cd

Related

Values after join are incorrect

I have 2 database tables. Table A has to fetch some records based on parameter passed there may or may not be an entry in table B with that key.
What I want to do is:
select a.col1,a.col2,a.col3
FROM table WHERE a.id = 123
This would fetch 20 rows. For one of the rows there is an entry in another table B.
select T_level from table b where b.id = 123
only one record appears with right value.
What I want is to get this in a single query. Something like:
select a.col1,a.col2,a.col3,b.T_level
from a,b
where a.id = 123
and a.id = b.id
When I do that, I get 20 rows and the column T_level as '50' for all the rows, whereas it should be '50' for one correct row, for rest it should be null.
I further tried:
select a.col1,a.col2,a.col3,nvl(b.T_level,0) from a,b
but that doesn't fetch the way I expect.
Firstly, please learn to use ansi sql join syntax. The Oracle join syntax you are using hasn't been considered good practice for decades
SQL Join syntax
If you want to get all records from a and any matching records from b then you need to use a LEFT OUTER JOIN

SQL joining without common keys

If I have a table with the following atributes:
A: id, race, key1
B: key1, driving_id
C: driving_id, fines
why would it be possible for us to have the following queries:
select A.id, A.race, B.key1, B.driving_id, C.fines
from A
left join B on A.key1=B.key1
left join C on B.driving_id= C.driving_id
even though there are no common keys for A and C in the last line of the SQL query?
The query that you have written is parsed as:
select A.id, A.race, B.key1, B.driving_id, C.fines
from (A left join
B
on A.key1 = B.key1
) left join
C
on B.driving_id = C.driving_id;
That is, C is -- logically -- being joined to the result of A and B. Any keys from those tables would be valid.
Although your original query is the preferable way to write it, you could also write:
select ab.id, ab.race, ab.key1, ab.driving_id, C.fines
from (select . . . -- whatever columns you need
from A left join
B
on A.key1 = B.key1
) ab left join
C
on ab.driving_id = C.driving_id;
The three versions are all equivalent, but the last one may help you better understand what is going on with joins between multiple tables.
Without seeing sample data from the three tables, we might not know for sure in the query makes any sense or would even run. Assuming it does run, then there should be nothing wrong with the join logic. For example, it is perfectly possible for table B to have a key key1 which relates to the A table, while at the same time having another key driving_id which relates to the C table. Note that either of these keys (but not both) could be a primary key in the B table, and if not then each key would be a foreign key.
The LEFT JOIN keyword returns all records from the left table (tableA), and the matched records from the right table (tableB). Furthermore, Similarly it returns all records from the result of first set, and the matched records from the right table (tableC). The result is NULL from the right side, if there is no match.
So A & C have a link through table B.

Inner join and cross apply. How does it get evaluated?

If Inner join is: For each row in the left table, find row in the right table where the condition is met.
What's is cross apply? I have read that it's just inner join which gets evaluated row by row, but isn't inner join also evaluated row by row?
How do you explain cross apply in plain English? Is it just inner join but allows more complicated joins?
APPLY is different from JOIN in that it allows for correlated subqueries. For instance:
SELECT ...
FROM outer
APPLY (
SELECT ..
FROM inner WHERE outer.column = inner.column
)
At first this does not seems much of a difference, until you consider relational functions. Since APPLY accepts correlations from the other side, it means you can pass it values as arguments to the function:
SELECT ...
FROM outer
APPLY function(outer.column)
This is something not possible with JOIN.
The CROSS vs. OUTER is the same as with JOINs'.
Inner Join (or simply join):
Given 2 tables, A, and B, and a condition C that correlates A and B (most commonly, an equality relation between 2 fields, one from A, and one from B), joining table A with B based on C means that, for each row in A, check for rows in B where C is met - and return them.
Translating it into an example:
SELECT * FROM A inner join B on A.field1 = B.field5
Here, for each row in A, check for rows in B where A's field1 equals B's field5.
Return all such rows.
Cross Join:
A join that is not based on an explicit condition - rather - it combines every row from A with every row from B, and returns such rows.
Assuming A has 10 rows and B 20, you would get a result set of 200 rows.
Cross Apply: (which I have just learned about thanks to you :)
A cross apply is indeed related to a cross join, hence it bears "cross" in its name as well. What happens in a cross apply, as far as I understand, is:
Given a table A, and a function F, for each row selected by a given select statement from A, cross join it with the results of F.
Let's say A has 10 rows, and F is simply a function that returns 3 constant rows, like
1
2
3
For each one of the 10 rows from A, you will cross join the 3 resulting rows from F. Resulting in a result set of 30 rows.
Now, for which purpose was this statement created, I think I can't help much.
What I can think of, after reading some SO threads, is that it provides performance gains in such cross join operations (you could achieve the same results without using a function such as F and the "Cross-Apply").
This post provides an example of a scenario where such performance gain is achieved.

SQL Query Results

I have to write a custom interpreter that simulates SQL select queries on a database with three tables: A, B, and C. My question is as follows: do the following queries return the same results?
select A1
from A
where A1 = 1;
select A1
from A, C
where A1 = 1;
As I have it written, these two provide different results, because of the added table in the from clause. But I'm not sure if that's right; should the results depend on the tables in the from clause or the joins (or lack thereof) in the where clause?
The Second will return all the rows matching de A where Clause and all the row from the C table. Since there is no relation defined between those table. It's often call a cartesian product.
If you want a relation between A and C you will need a join between those, such as A.C_ID = C.ID for a matching pattern, or LEFT | RIGHT join depending on the set of result you want.

vb.net compare two tables and find differences

I have two tables with the same strucure. a.ID*(varchar(10)), a.CODE_ASS(varchar(1))* and b.ID*(varchar(10)), b.CODE_ASS(varchar(1))*
Table "a" contains 2010 data, and table "b" contain 2013 data.
These two tables should doesn't have the same number of rows in each, but common IDs should be identical. I need to compare tables and find differences.
As you can see in this example, green rows are ok, and red one should be an error.
ID 2, 4 and 5 are errors because there are some differences. ID 6, in "a" table, is ok even if it has been deleted in table "b".
It appears that you are using SQL tables, if you write a query to join the data on ID and select only where the values are different. Do you really want to assume that 0 = NULL?
SELECT a.ID FROM a INNER JOIN b ON a.ID = b.ID WHERE a.ID<>b.ID;
If you want 0 = NULL then you need to change NULLs to 0 - that would look like the following.
SELECT a.ID FROM a INNER JOIN b ON a.ID = b.ID WHERE ISNULL(a.ID,0)<>ISNULL(b.ID,0);
ISNULL(param, value) will change the NULL to the value, in this case 0.
I am guessing you are using a recordset object so then all you have to do is loop through the results.