Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

2 Outer Joins on Same Table?

Tags:

sql

join

oracle

Here is a question which has been boggling me for few days now, and I searched and searched but couldn't find any convincing answer !

Simple question, why is it restricted to have 2 Outer Joins in SQL, on same table even with different columns being used, check the queries below for better understanding. Also I can overcome them using nested sub query or ANSI joins, but then why it is even restricted in the first place using (+) operator!

In this question I'm referring to the error :

ORA-01417: a table may be outer joined to at most one other table

What I want to ask is why this is allowed :

select * from
a, b, c
where a.a1 = b.b1
and a.a2 = c.c1

And why this is not allowed:

select * from
a, b, c
where a.a1(+) = b.b1
and a.a2(+) = c.c1

Please leave ANSI and Nested SubQueries alone

like image 417
Shubham Gupta Avatar asked Jun 14 '13 20:06

Shubham Gupta


2 Answers

The restriction is described in Oracle documentation: Outer Joins

Oracle recommends that you use the FROM clause OUTER JOIN syntax rather than the Oracle join operator. Outer join queries that use the Oracle join operator (+) are subject to the following rules and restrictions, which do not apply to the FROM clause OUTER JOIN syntax:

...

In a query that performs outer joins of more than two pairs of tables, a single table can be the null-generated table for only one other table. For this reason, you cannot apply the (+) operator to columns of B in the join condition for A and B and the join condition for B and C. Refer to SELECT for the syntax for an outer join.

which basically means (described in ANSI/ISO syntax) that you can't have with the old (+) syntax what is perfectly valid in ANSI/ISO:

--- Query 1 ---
  a 
RIGHT JOIN b
  ON a.x = b.x
RIGHT JOIN c 
  ON a.y = c.y

or:

--- Query 1b ---
  c 
LEFT JOIN 
    b LEFT JOIN a
        ON a.x = b.x 
  ON a.y = c.y

That's only one of the many restrictions of the old Oracle syntax.


As for the reasons for this restriction, it may be implementation details or/and the ambiguity of such joins. While the two joins above are 100% equivalent, the following is not equivalent to the above two:

--- Query 2 ---
  a 
RIGHT JOIN c 
  ON a.y = c.y 
RIGHT JOIN b
  ON a.x = b.x 

See the test in SQL-Fiddle. So the question arises. How should the proprietary join be interpreted, as query 1 or 2?

FROM a, b, c 
WHERE a.y (+) = c.y 
  AND a.x (+) = b.x 

There is no restriction if a table appears on the left side of (2 or more) outer joins. These are perfectly valid, even with the old syntax:

FROM a
  LEFT JOIN b ON a.x = b.x 
  LEFT JOIN c ON a.y = c.y
  ...
  LEFT JOIN z ON a.q = z.q

FROM a, b, ..., z
WHERE a.x = b.x (+) 
  AND a.y = c.y (+)
  ...
  AND a.q = z.q (+)
like image 119
ypercubeᵀᴹ Avatar answered Oct 11 '22 02:10

ypercubeᵀᴹ


I strongly suggest to use explicit OUTER JOIN syntax. Starting from Oracle 12c this restriction is relaxed 1.4.3 Enhanced Oracle Native LEFT OUTER JOIN Syntax:

In previous releases of Oracle Database, in a query that performed outer joins of more than two pairs of tables, a single table could be the null-generated table for only one other table. Beginning with Oracle Database 12c, a single table can be the null-generated table for multiple tables.

Code:

CREATE TABLE a AS
SELECT 1 AS a1, 2 AS a2 FROM dual;

CREATE TABLE b AS
SELECT 1 AS b1 FROM dual;

CREATE TABLE c AS
SELECT 3 AS c1 FROM dual;

-- Oracle 12c: code below will work
SELECT * 
FROM a, b, c
WHERE a.a1(+) = b.b1
  AND a.a2(+) = c.c1;

Output:

A1  A2  B1  C1
-   -   1   3

db<>fiddle demo - Oracle 11g will return error

db<>fiddle demo Oracle 12c/18c will return resultset

like image 24
Lukasz Szozda Avatar answered Oct 11 '22 03:10

Lukasz Szozda