Query featuring outer joins behaves differently in Oracle 12c
UPDATE: This is fixed in 12.1.0.2.
This definitely looks like a bug in 12.1.0.1. I would encourage you to create a service request through Oracle support. They might be able to find a fix or a better work around. And hopefully Oracle can fix it in a future version for everyone. Normally the worst part about working with support is reproducing the issue. But since you already have a very good test case this issue may be easy to resolve.
There are probably many ways to work around this bug. But it's difficult to tell which method will always work. Your query re-write may work now, but if optimizer statistics change perhaps the plan will change back in the future.
Another option that works for me on 12.1.0.1.0 is:
ALTER SESSION SET optimizer_features_enable='11.2.0.3';
But you'd need to remember to always change this setting before the query is run, and then change it back to '12.1.0.1' after. There are ways to embed that within a query hint, such as /*+ OPT_PARAM('optimizer_features_enable' '11.2.0.3') */
. But for some reason that does not work here. Or perhaps you can temporarily set that for the entire system and change it back after a fix or better work around is available.
Whichever solution you use, remember to document it. If a query looks odd the next developer may try to "fix" it and hit the same problem.
Performance issues with outer joins to view in Oracle 12c
We discovered the cause of the performance issue. The following 2 system parameters were changed at the system level by the DBAs for the main application that uses our client's Oracle server:
_optimizer_cost_based_transformation = OFF
_optimizer_reduce_groupby_key = FALSE
When we changed them at the session level to the following, the query above that joins the 2 views returns results in less than 2 seconds:
alter session set "_optimizer_cost_based_transformation"=LINEAR;
alter session set "_optimizer_reduce_groupby_key" = TRUE;
COMMIT;
Changing this parameter did not have an impact on performance:
alter session set optimizer_adaptive_features=FALSE;
COMMIT;
We also found that changing the following parameter improved performance even more for our more complex views:
alter session set optimizer_features_enable="11.2.0.3";
COMMIT;
Column outer joined in subquery (ORA-01799)
You may use CTE with row_number
to classify the row with the minimal REV_ID
and the outer join only to those rows.
The advantage is this approach works even if you want some other attributes from T1
with t1_min as
(select REC_ID, REV_ID,
row_number() over (partition by REC_ID order by REV_ID) as rn
from TABLE_1)
SELECT t2.rec_id t2_rec_id,t1.rec_id t1_rec_id,
t1.rev_id
from TABLE_2 T2
LEFT OUTER JOIN t1_min T1 on T1.REC_ID = T2.REC_ID
and t1.rn = 1
T2_REC_ID T1_REC_ID REV_ID
---------- ---------- ----------
1 1 23
2 2 19
What is the difference between INNER JOIN and OUTER JOIN?
Assuming you're joining on columns with no duplicates, which is a very common case:
An inner join of A and B gives the result of A intersect B, i.e. the inner part of a Venn diagram intersection.
An outer join of A and B gives the results of A union B, i.e. the outer parts of a Venn diagram union.
Examples
Suppose you have two tables, with a single column each, and data as follows:
A B
- -
1 3
2 4
3 5
4 6
Note that (1,2) are unique to A, (3,4) are common, and (5,6) are unique to B.
Inner join
An inner join using either of the equivalent queries gives the intersection of the two tables, i.e. the two rows they have in common.
select * from a INNER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b;
a | b
--+--
3 | 3
4 | 4
Left outer join
A left outer join will give all rows in A, plus any common rows in B.
select * from a LEFT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a = b.b(+);
a | b
--+-----
1 | null
2 | null
3 | 3
4 | 4
Right outer join
A right outer join will give all rows in B, plus any common rows in A.
select * from a RIGHT OUTER JOIN b on a.a = b.b;
select a.*, b.* from a,b where a.a(+) = b.b;
a | b
-----+----
3 | 3
4 | 4
null | 5
null | 6
Full outer join
A full outer join will give you the union of A and B, i.e. all the rows in A and all the rows in B. If something in A doesn't have a corresponding datum in B, then the B portion is null, and vice versa.
select * from a FULL OUTER JOIN b on a.a = b.b;
a | b
-----+-----
1 | null
2 | null
3 | 3
4 | 4
null | 6
null | 5
Related Topics
T-SQL Column Alias on Computed Column - Invalid Column Name
Differencebetween Prepared Statements and SQL or Pl/Pgsql Functions, in Terms of Their Purpose
How to Open Bcp Host Data-File
Find the Length of the Longest Row in a Column in Oracle
Self Join to Get Employee Manager Name
Blank Values in Date Column Returning as 1900/01/01 on Running Select Statement
How to Subtract 2 Dates in Oracle to Get the Result in Hour and Minute
How to Make Comment Reply Query in MySQL
How to Create Alternative Row Background Colors in Ssrs for Values in a Group
How to Concatenate Multiple Rows
Splitting Variable Length Delimited String Across Multiple Rows (Sql)
How to Get the Latest Record for Each Item in Cosmosdb Using SQL
Oracle SQL: the Insert Query with Regexp_Substr Expression Is Very Long ( Split String )
Generate a Sequential Number (Per Group) When Adding a Row to an Access Table
Entity Framework and Cross/Outer Apply