In this case, you didn't want to use the outer join syntax at all.
You wanted to say:
I want every row in A joined to B by a.id = b.id and if there is no match in B for a row in A - output A anyway with NULL's for B.*
Then, further filter this result by applying the predicate "a.value < nvl(b.max_value,0.5)" - that'll be applied after any outer joining takes place.
The way you wrote it has A being outer joined to f(B) with an inequality - if we do the processing ( f(x) - the nvl ) and outer join to the result... you get what you get.
See, if we add a row, you can see this:
ops$tkyte%ORA11GR2> insert into mbtemp_limits( id, max_value ) values ( 4, null );
1 row created.
ops$tkyte%ORA11GR2>
ops$tkyte%ORA11GR2> select a.id, a.value, b.*
2 from mbtemp a, mbtemp_limits b
3 where a.id = b.id(+)
4 and a.value < nvl(b.max_value(+),0.5)
5 /
ID VALUE ID MAX_VALUE
---------- ---------- ---------- ----------
1 .25 1 .3
4 .0001 4
3 .9999
2 .75
see how the row for ID=4 was not made up in B, the join "succeeded". A.id was joined to B.id and a.value was in fact less than nvl(b.max_value,0.5)
the (+) is associated with a column but applies to the expression. You can see this with other expressions as well:
ops$tkyte%ORA11GR2> select a.id, a.value, b.*
2 from mbtemp a, mbtemp_limits b
3 where a.id = b.id(+)
4 and a.value < decode(b.max_value(+),0.25,-1,null,0.5)
5 /
ID VALUE ID MAX_VALUE
---------- ---------- ---------- ----------
4 .0001 4
3 .9999
1 .25
2 .75
In that case, we can see the decode was done AND THEN the join. we turned 0.25 into -1 and null again into 0.5. Then we joined and the join "succeeded", we didn't need to make up a row for id=4 in B.
further, we have to be consistent - if you reference that column again in the expression - it has to use (+) there too:
ops$tkyte%ORA11GR2> select a.id, a.value, b.*
2 from mbtemp a, mbtemp_limits b
3 where a.id = b.id(+)
4 and a.value < decode(b.max_value(+),0.25,-1,null,0.5,b.max_value)
5 /
and a.value < decode(b.max_value(+),0.25,-1,null,0.5,b.max_value)
*
ERROR at line 4:
ORA-01417: a table may be outer joined to at most one other table
ops$tkyte%ORA11GR2> select a.id, a.value, b.*
2 from mbtemp a, mbtemp_limits b
3 where a.id = b.id(+)
4 and a.value < decode(b.max_value(+),0.25,-1,null,0.5,b.max_value(+))
5 /
ID VALUE ID MAX_VALUE
---------- ---------- ---------- ----------
1 .25 1 .3
4 .0001 4
3 .9999
2 .75
but in any case - the outer join on that part of the where clause was inappropriate if you type out your requirement in a sentence. You in fact wanted the results of A left join to B on ID to be filtered by the NVL() function.