Oracle outer join with filter condition on the second table - sql

Is there any condition under which the result sets will be different from the following two statements?
select * from a,b where a.id = b.id and b.name = 'XYZ'
select * from a,b where a.id =b.id(+) and b.name = 'XYZ'
I think in both cases it will bring the common rows from a and b where b.name = 'XYZ'. So a.id = b.id(+) has no meaning.

No, there is no condition under which the result sets will be different.
But your assumption "a.id = b.id(+) has no meaning" is not 100% correct. It has a meaning, because it defines the join, otherwise this would be a cartesian product of a and b with all rows from a and b.name = 'XYZ'.
What has no effect is the (+), because the statement is "semantically" wrong. It makes no sense to outer join on id but to join on name.
Usually something like that is wanted:
select * from a,b where a.id =b.id(+) and b.name(+) = 'XYZ';
Short example at http://www.sqlfiddle.com/#!4/d19b4/15

Related

Filter on the column on which two tables are joined

Are next two queries going to return same result set?
SELECT * FROM tableA a
JOIN tableB b
ON a.id = b.id
WHERE a.id = '5'
--------------------------------
SELECT * FROM tableA a
JOIN tableb b
ON a.id = b.id
WHERE b.id = '5'
Also, will answer be different if LEFT JOIN is used instead of JOIN?
As written, they will return the same result.
The two will not necessarily return the same result with a left join.
Yes the result will be the same.
With a left join you will get every dataset of both table who got a ID.
With a join (Inner Join) you will get only the dataset's who a.id = b.id.
This site will explain you how to join https://www.w3schools.com/sql/sql_join.asp
Yes they will. A simple join works like an inner join by default. It checks for instances where the item you're joining on exist on both tables. Since you're joining on where a.id=b.id the results will be the same.
If you change the type of join to a left, the results will include all a.id's regardless of whether they are equal to 5.

How to use oracle outer join with a filter where clause

If i write a sql:
select *
from a,b
where a.id=b.id(+)
and b.val="test"
and i want all records from a where corresponding record in b does not exist or it exists with val="test", is this the correct query?
You're much better off using the ANSI syntax
SELECT *
FROM a
LEFT OUTER JOIN b ON( a.id = b.id and
b.val = 'test' )
You can do the same thing using Oracle's syntax as well but it gets a bit hinkey
SELECT *
FROM a,
b
WHERE a.id = b.id(+)
AND b.val(+) = 'test'
Note that in both cases, I'm ignoring the c table since you don't specify a join condition. And I'm assuming that you don't really want to join A to B and then generate a Cartesian product with C.
Move the condition into the JOIN clause and use the ANSI standard join pattern.
SELECT NameYourFields,...
FROM A
LEFT OUTER JOIN B
ON A.ID = B.ID
AND B.VAL = 'test'
INNER JOIN C
ON ...
A LEFT OUTER JOIN is one of the JOIN operations that allow you to specify a join clause. It preserves the unmatched rows from the first (left) table, joining them with a NULL row in the shape of the second (right) table.
So you can do as follows :
SELECT
FROM a LEFT OUTER JOIN b
ON a.id = b.id
--Note that you have used double quote "test" which is not used for varchar in SQL you should use single quote 'test'
AND b.val = 'test';
SELECT * FROM abc a, xyz b
WHERE a.id = b.id
AND b.val = 'test'

Write correlated subquery in a WHERE Clause as join

I have a query like below:
select
a.id, a.title, a.description
from
my_table_name as a
where
a.id in (select id from another_table b where b.id = 1)
My question is, is there any way I can avoid the subquery in where clause and use it in from clause itself without compromising of performance?
Both of the answers given so far are incorrect in the general case (though the database may have unique constraints which ensure they are correct in a specific case)
If another_table might have multiple rows with the same id then the INNER JOIN will bring back duplicates that are not present in the IN version. Trying to remove them with DISTINCT can change the semantics if the columns from my_table_name themselves have duplicates.
A general rewrite would be
SELECT a.id,
a.title,
a.description
FROM my_table_name AS a
JOIN (SELECT DISTINCT id
FROM another_table
WHERE id = 1) AS b
ON b.id = a.id
The performance characteristics of this rewrite are implementation dependant.
You may use INNER JOIN as:
select
a.id, a.title, a.description
from
my_table_name as a INNER JOIN another_table as b ON (a.id = b.id and b.id = 1)
Or
select
a.id, a.title, a.description
from
my_table_name as a INNER JOIN another_table as b ON a.id = b.id
where b.id = 1
Both the queries may not return the same value for you. You may choose whatever works for you. Please use this as a starting point and not as a copy-paste code.
To express it as a join:
select distinct
a.id, a.title, a.description
from my_table_name as a
join another_table b on b.id = a.id
where b.id = 1
The use of distinct is to produce the same results in case another_table has the same id more than once so the same row doesn't get returned multiple times.
Note: if combinations of id, name and description in my_table_name are not unique, this query won't return such duplicates as the original query would.
To guarantee to produce the same results, you need to ensure that the id's in another_table is unique. To do this as a join:
select
a.id, a.title, a.description
from my_table_name as a
join (select distinct id from another_table) b on b.id = a.id
where b.id = 1

How can you perform a join when also using a comma-separated list of tables in an SQL select statement?

This is evidently correct syntax in SQL Server:
SELECT a.id, b.name
FROM Table1 a, Table2 b
WHERE a.id = b.fk1
So is this:
SELECT a.id, c.status
FROM Table1 a
JOIN Table3 c ON a.id = c.fk2
But this apparently isn't:
SELECT a.id, b.name, c.status
FROM Table1 a, Table2 b
JOIN Table3 c ON a.id = c.fk2
WHERE a.id = b.fk1
I would NOT normally want to construct a query in the third case's style (and really not the first case's either), but it would probably be the path of least resistence in editing some code that's already been written at my company. Somebody used the first form with five different tables, and I really need to work in a sixth table through a JOIN statement, without taking chances of messing up what they already have. Even though I could re-write their stuff outright if I need to, I would really like to know how to do something like in the third case.
Running the code exactly as-is in the examples, the third case gives me this error message:
The multi-part identifier "a.id" could not be bound.
What is syntactically breaking the third case? What simple fix could be applied? Thanks!
I, likewise, would not recommend doing this. But, you can just change the , to a cross join:
SELECT a.id, b.name, c.status
FROM Table1 a cross join Table2 b
JOIN Table3 c ON a.id = c.fk2
WHERE a.id = b.fk1
This code:
SELECT a.id, b.name, c.status
FROM Table1 a, Table2 b
JOIN Table3 c ON a.id = c.fk2
WHERE a.id = b.fk1
is doing a cross join on a and the result of an inner join on b and c. c cannot access any of the fields in a because the join is being performed on b. what you should do is change your query to:
SELECT a.id, b.name, c.status
FROM Table1 a
inner join Table2 b on a.id = b.fk1
inner JOIN Table3 c ON a.id = c.fk2

ORACLE/SQL - Joining 3 tables that aren't all interconnected

I need help joining 3 tables where they are not all interconnected
So lets say I have tables A, B, C
here are the relations
A.type = B.type
A.model = C.model
What I need to do is inner join A and B and return all the matched A records. Next I need to pull the records from C that match on the prior join.
Or in other words all the records in C that are in A where A is in B
Hope that makes sense. Sorry for no data examples.
I have tried this
select
c.*
from
c, a, b
where
c.model_ = a.model_
and a.type_ = b.type_
but receive this message 'Errors: Query has MERGE JOIN CARTESIAN. You must correct where-clause to properly join tables in the select statement.'
I know this is a matter of style but in my opinion ansi style joins make this much clearer:
SELECT c.*
FROM c
JOIN a ON a.model = c.model
JOIN b on b.type = a.type
In case you have multiple matching elements in a or b, this query will return duplicates. You can either add a DISTINCT or rewrite it as an EXISTS query:
SELECT *
FROM c
WHERE EXISTS (SELECT 1
FROM a
JOIN b ON b.type = a.type
WHERE a.model = c.model)
I think this should also give the same result, as long as there are no NULL values in model:
SELECT *
FROM c
WHERE c.model IN (SELECT a.model
FROM a
JOIN b ON b.type = a.type)
simply also join to C with an AND condition
Without the data samples, it is difficult to understand the actual problem and validate the query.
did you try..
Select c.*
from a,b,c
where a.type = b.type
and a.model = c.model;
Are your losing some records or seeing extra records that you don't expect to see?
The above query will only give you records in c that are in a and where a records match the criterion in b.