Re: prefer (+) oracle notation - Mailing list pgsql-general
| From | Tom Lane |
|---|---|
| Subject | Re: prefer (+) oracle notation |
| Date | |
| Msg-id | 16991.972007161@sss.pgh.pa.us Whole thread Raw |
| In response to | RE: prefer (+) oracle notation ("Edmar Wiggers" <edmar@brasmap.com>) |
| Responses |
RE: prefer (+) oracle notation. Let's use standard and that's it
|
| List | pgsql-general |
"Edmar Wiggers" <edmar@brasmap.com> writes:
> select a.id,a.size,b.*,c.id,c.color
> from table_a a, table_b b, table_c c
> where
> a.b_id = b.id and
> a.c_id = c.id(+) and
> a.size < 1000 and
> b.weight > 10;
> This is a select from 3 tables, where a and b are regularly joined, but c is
> outer joined. That is, the query is likely to return null values on c.id and
> c.color.
Yes, but outer joined *to what*? And what aspect of the syntax decides
that? The problem with this syntax is that it's not apparent when the
WHERE-clause conditions are applied. At least not to me.
The problem can be seen most easily when there are additional
restrictions on table C. Actually we don't need 3 tables, so consider
select * from table_a a, table_b b
where
a.id = b.id(+) and
b.weight > 10;
with data
a.id
1
2
b.id b.weight
1 20
2 5
Clearly we will get a row 1,1,20, and we will *not* get a row 2,2,5.
But will we get a row 2,NULL,NULL, or not? If the outer join occurs
after we remove b rows with weight<=10, then there will be no row
matching a.id=2, so the outer join will produce a row 2,NULL,NULL.
If it's done in the other order, the outer join will produce a row
2,2,5, which will then be discarded due to the condition weight>10,
so no row out. The ISO syntax allows both these behaviors to be
expressed unambiguously:
... FROM a LEFT JOIN b ON (a.id = b.id AND b.weight > 10)
... FROM a LEFT JOIN b ON (a.id = b.id) WHERE b.weight > 10
whereas the Oracle syntax is very ambiguous --- please don't tell me
that it depends on the ordering of the AND clauses in the WHERE!
(You may argue that 2,NULL,NULL violates the condition b.weight > 10,
but that's just an artifact of trying to simplify the example as much
as possible. If I write
where
a.id = b.id(+) and
(b.weight > 10 OR b IS NULL);
then it's absolutely unclear which result the Oracle syntax should
produce.)
It gets a lot worse if there are multiple tables being outer-joined,
since then it will depend on the join order whether you get certain
part-NULL rows out or not, and I see no way to define the join order
in the Oracle syntax.
> I believe the standard syntax for that might be:
> select a.id,a.size,b.*,c.id,c.color
> from ((table_a a join table_b b on a.b_id = b.id) outer join table_c c on
> a.c_id = b.id)
> where
> a.size < 1000 and
> b.weight > 10;
> To me, not so readable. But of course I can live with that.
Like I said, I don't much care for the ISO syntax either --- it's
very verbose. But it's unambiguous what will happen...
regards, tom lane
pgsql-general by date: