Re: prefer (+) oracle notation

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: "Edmar Wiggers" <edmar(at)brasmap(dot)com>
Cc: "pgsql-general" <pgsql-general(at)postgresql(dot)org>
Subject: Re: prefer (+) oracle notation
Date: 2000-10-20 01:59:21
Message-ID: 16991.972007161@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

"Edmar Wiggers" <edmar(at)brasmap(dot)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

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Alex Pilosov 2000-10-20 02:03:07 Re: MySQL -> pgsql
Previous Message Alex Pilosov 2000-10-20 01:53:29 RE: MySQL -> pgsql