Thread: Outer join differences

Outer join differences

From
Yuva Chandolu
Date:
Hi,

I see different results in Oracle and postgres for same outer join queries.
Here are the details.

I have the following tables in our pg db

table: yuva_test1
yt1_id        yt1_name    yt1_descr
1        1-name1    1-desc1
2        1-name2    1-desc2
3        1-name3    1-desc3
4        1-name4    1-desc4
5        1-name5    1-desc5
6        1-name6    1-desc6

table: yuva_test2
yt2_id        yt2_name    yt2_descr
2        2-name2    2-desc2
3        2-name3    2-desc3
4        2-name4    2-desc4

When I run the query "select yt1_name, yt1_descr, yt2_name, yt2_descr from
yuva_test1 left outer join yuva_test2 on yt1_id=yt2_id and yt2_name =
'2-name2'" on postgres database I get the following results

yt1_name    yt1_descr    yt2_name    yt2_descr
1-name1    1-descr1
1-name2    1-descr2    2-name2    2-descr2
1-name3    1-descr3
1-name4    1-descr4
1-name5    1-descr5
1-name6    1-descr6

But when I tried the same on Oracle(8.1.7) (the query is "select yt1_name,
yt1_descr, yt2_name, yt2_descr from yuva_test1, yuva_test2 where
yt1_id=yt2_id(+) and yt2_name = '2-name2'') I get the following results

yt1_name    yt1_descr    yt2_name    yt2_descr
1-name2    1-descr2    2-name2    2-descr2

Why postgres is giving? which is standard? is it a bug? or is it the way
postgres is implemented? Could some one help me?

Note: at the end of my mail is script to create tables and data in postgres.

Thanks
Yuva
Sr. Java Developer
www.ebates.com

============================================================
Scripts:
CREATE TABLE "yuva_test1" ( "yt1_id" numeric(16, 0),  "yt1_name" varchar(16) NOT NULL,  "yt1_descr" varchar(32)
) WITH OIDS;

CREATE TABLE "yuva_test2" ( "yt2_id" numeric(16, 0),  "yt2_name" varchar(16) NOT NULL,  "yt2_descr" varchar(32)
) WITH OIDS;

insert into yuva_test1 (yt1_id, yt1_name, yt1_descr) values (1, '1-name1',
'1-descr1');
insert into yuva_test1 (yt1_id, yt1_name, yt1_descr) values (2, '1-name2',
'1-descr2');
insert into yuva_test1 (yt1_id, yt1_name, yt1_descr) values (3, '1-name3',
'1-descr3');
insert into yuva_test1 (yt1_id, yt1_name, yt1_descr) values (4, '1-name4',
'1-descr4');
insert into yuva_test1 (yt1_id, yt1_name, yt1_descr) values (5, '1-name5',
'1-descr5');
insert into yuva_test1 (yt1_id, yt1_name, yt1_descr) values (6, '1-name6',
'1-descr6');

insert into yuva_test2 (yt2_id, yt2_name, yt2_descr) values (2, '2-name2',
'2-descr2');
insert into yuva_test2 (yt2_id, yt2_name, yt2_descr) values (3, '2-name3',
'2-descr3');
insert into yuva_test2 (yt2_id, yt2_name, yt2_descr) values (4, '2-name4',
'2-descr4');
============================================================


Re: Outer join differences

From
Tom Lane
Date:
Yuva Chandolu <ychandolu@ebates.com> writes:
> I see different results in Oracle and postgres for same outer join queries.

I believe you are sending your bug report to the wrong database.

> When I run the query "select yt1_name, yt1_descr, yt2_name, yt2_descr from
> yuva_test1 left outer join yuva_test2 on yt1_id=yt2_id and yt2_name =
> '2-name2'" on postgres database I get the following results

> yt1_name    yt1_descr    yt2_name    yt2_descr
> 1-name1    1-descr1
> 1-name2    1-descr2    2-name2    2-descr2
> 1-name3    1-descr3
> 1-name4    1-descr4
> 1-name5    1-descr5
> 1-name6    1-descr6

> But when I tried the same on Oracle(8.1.7) (the query is "select yt1_name,
> yt1_descr, yt2_name, yt2_descr from yuva_test1, yuva_test2 where
> yt1_id=yt2_id(+) and yt2_name = '2-name2'') I get the following results

> yt1_name    yt1_descr    yt2_name    yt2_descr
> 1-name2    1-descr2    2-name2    2-descr2

According to the SQL spec, the output of a LEFT JOIN consists of those
joined rows where the join condition is true, plus those rows of the
left table for which no right-table row produced a true join condition
(substituting nulls for the right-table columns).  Our output clearly
conforms to the spec.

I do not know what Oracle thinks is the correct output when one
condition is marked with (+) and the other is not --- it's not very
obvious what that corresponds to in the spec's terminology.  But I
suggest you take it up with them, not us.
        regards, tom lane


Re: Outer join differences

From
Yuva Chandolu
Date:
Hi Tom,

Thanks for your prompt reply, after second thought(before receiving your
reply) I realized that postgres is doing more logically - i.e if the outer
join condition returns false then replace by nulls for right table columns.
We may change our code accordingly :-(.

Thanks
Yuva


-----Original Message-----
From: Tom Lane [mailto:tgl@sss.pgh.pa.us]
Sent: Tuesday, July 30, 2002 9:15 PM
To: Yuva Chandolu
Cc: 'pgsql-hackers@postgresql.org'
Subject: Re: [HACKERS] Outer join differences 


Yuva Chandolu <ychandolu@ebates.com> writes:
> I see different results in Oracle and postgres for same outer join
queries.

I believe you are sending your bug report to the wrong database.

> When I run the query "select yt1_name, yt1_descr, yt2_name, yt2_descr from
> yuva_test1 left outer join yuva_test2 on yt1_id=yt2_id and yt2_name =
> '2-name2'" on postgres database I get the following results

> yt1_name    yt1_descr    yt2_name    yt2_descr
> 1-name1    1-descr1
> 1-name2    1-descr2    2-name2    2-descr2
> 1-name3    1-descr3
> 1-name4    1-descr4
> 1-name5    1-descr5
> 1-name6    1-descr6

> But when I tried the same on Oracle(8.1.7) (the query is "select yt1_name,
> yt1_descr, yt2_name, yt2_descr from yuva_test1, yuva_test2 where
> yt1_id=yt2_id(+) and yt2_name = '2-name2'') I get the following results

> yt1_name    yt1_descr    yt2_name    yt2_descr
> 1-name2    1-descr2    2-name2    2-descr2

According to the SQL spec, the output of a LEFT JOIN consists of those
joined rows where the join condition is true, plus those rows of the
left table for which no right-table row produced a true join condition
(substituting nulls for the right-table columns).  Our output clearly
conforms to the spec.

I do not know what Oracle thinks is the correct output when one
condition is marked with (+) and the other is not --- it's not very
obvious what that corresponds to in the spec's terminology.  But I
suggest you take it up with them, not us.
        regards, tom lane


Re: Outer join differences

From
Stephan Szabo
Date:
On Tue, 30 Jul 2002, Yuva Chandolu wrote:

> Hi,
>
> I see different results in Oracle and postgres for same outer join queries.
> Here are the details.

Those probably aren't the same outer join queries.

> When I run the query "select yt1_name, yt1_descr, yt2_name, yt2_descr from
> yuva_test1 left outer join yuva_test2 on yt1_id=yt2_id and yt2_name =
> '2-name2'" on postgres database I get the following results
>

Both conditions are part of the join condition for the outer join.

> But when I tried the same on Oracle(8.1.7) (the query is "select yt1_name,
> yt1_descr, yt2_name, yt2_descr from yuva_test1, yuva_test2 where
> yt1_id=yt2_id(+) and yt2_name = '2-name2'') I get the following result

One condition is the join condition and one is a general where condition I
would guess since only one has the (+)

I think the equivalent query is
select yt1_name, yt1_descr, yt2_name, yt2_descr from yuva_test1 left outer
join yuva_test2 on yt1_id=yt2_id where yt2_name='2-name2'.

Note of course that you're destroying the outer joinness by doing
that yt2_name='2-name2' since the rows with no matching yuva_test2
will not match that conditoin.



Re: Outer join differences

From
"Christopher Kings-Lynne"
Date:
> > When I run the query "select yt1_name, yt1_descr, yt2_name,
> yt2_descr from
> > yuva_test1 left outer join yuva_test2 on yt1_id=yt2_id and yt2_name =
> > '2-name2'" on postgres database I get the following results

Probaly if you change your postgres query to this, it will give the same
answer as Oracle:

select yt1_name, yt1_descr, yt2_name,
yt2_descr from
yuva_test1 left outer join yuva_test2 on yt1_id=yt2_id where yt2_name =
'2-name2';

??

Chris


> > But when I tried the same on Oracle(8.1.7) (the query is
> "select yt1_name,
> > yt1_descr, yt2_name, yt2_descr from yuva_test1, yuva_test2 where
> > yt1_id=yt2_id(+) and yt2_name = '2-name2'') I get the following result

And maybe if you change the oracle query to this, it will give the same
answer as postgres:

select yt1_name,
yt1_descr, yt2_name, yt2_descr from yuva_test1, yuva_test2 where
yt1_id=yt2_id(+) and yt2_name = '2-name2'(+);

Just guessing tho.

Chris



Re: Outer join differences

From
Yuva Chandolu
Date:
This is great, we thought we may go for code changes, we will go with this
solution instead.

Thanks
Yuva

-----Original Message-----
From: Stephan Szabo [mailto:sszabo@megazone23.bigpanda.com]
Sent: Tuesday, July 30, 2002 9:31 PM
To: Yuva Chandolu
Cc: 'pgsql-hackers@postgresql.org'
Subject: Re: [HACKERS] Outer join differences



On Tue, 30 Jul 2002, Yuva Chandolu wrote:

> Hi,
>
> I see different results in Oracle and postgres for same outer join
queries.
> Here are the details.

Those probably aren't the same outer join queries.

> When I run the query "select yt1_name, yt1_descr, yt2_name, yt2_descr from
> yuva_test1 left outer join yuva_test2 on yt1_id=yt2_id and yt2_name =
> '2-name2'" on postgres database I get the following results
>

Both conditions are part of the join condition for the outer join.

> But when I tried the same on Oracle(8.1.7) (the query is "select yt1_name,
> yt1_descr, yt2_name, yt2_descr from yuva_test1, yuva_test2 where
> yt1_id=yt2_id(+) and yt2_name = '2-name2'') I get the following result

One condition is the join condition and one is a general where condition I
would guess since only one has the (+)

I think the equivalent query is
select yt1_name, yt1_descr, yt2_name, yt2_descr from yuva_test1 left outer
join yuva_test2 on yt1_id=yt2_id where yt2_name='2-name2'.

Note of course that you're destroying the outer joinness by doing
that yt2_name='2-name2' since the rows with no matching yuva_test2
will not match that conditoin.


Re: Outer join differences

From
Thomas Lockhart
Date:
> This is great, we thought we may go for code changes, we will go with this
> solution instead.

But you did catch Stephan's point that an outer join is not required to
produce the result you apparently want? The equivalent inner join will
be at worst just as fast, and possibly faster, both for PostgreSQL and
for Oracle...
                 - Thomas


Re: Outer join differences

From
Mario Weilguni
Date:
> > Here are the details.
>
> Those probably aren't the same outer join queries.

I think you're right, these aren't the same, see below:

>
> > When I run the query "select yt1_name, yt1_descr, yt2_name, yt2_descr
> > from yuva_test1 left outer join yuva_test2 on yt1_id=yt2_id and yt2_name
> > = '2-name2'" on postgres database I get the following results
>
> Both conditions are part of the join condition for the outer join.
>
> > But when I tried the same on Oracle(8.1.7) (the query is "select
> > yt1_name, yt1_descr, yt2_name, yt2_descr from yuva_test1, yuva_test2
> > where yt1_id=yt2_id(+) and yt2_name = '2-name2'') I get the following
> > result

I think for Oracle the equivalent is:
select yt1_name,      yt1_descr,       yt2_name,       yt2_descr  from yuva_test1,       yuva_test2 where yt2_id (+)=
yt1_id=yt2_id and yt2_name (+)= '2-name2' 



Re: Outer join differences

From
Jill Rabinowitz
Date:
Yuva,

The results make sense to me. The left outer join functionality in Postgres
is explained as follows:

LEFT OUTER JOIN returns all rows in the qualified Cartesian product (i.e.,
all combined rows that pass its ON condition), plus one copy of each row in
the left-hand table for which there was no right-hand row that passed the ON
condition. This left-hand row is extended to the full width of the joined
table by inserting NULLs for the right-hand columns. Note that only the
JOIN's own ON or USING condition is considered while deciding which rows
have matches. Outer ON or WHERE conditions are applied afterwards. 
So, in your postgres statement, you are retrieving all rows from yuva_test1,
and the one row from yuva_test2 that satisfied the "where" criteria that
yt2_name = '2-name2'.
In Oracle, though,  since your outer join is on yuva_test2, you would need
to specify an outer join on the criterion "yt2_name = '2-name2''" by saying
"yt2_name (+) = '2-name2''" to limit the resultset.
Hope this helps
Jill

>  -----Original Message-----
> From:     Yuva Chandolu  
> Sent:    Tuesday, July 30, 2002 8:53 PM
> To:    'pgsql-hackers@postgresql.org'
> Subject:    Outer join differences
> 
> Hi,
> 
> I see different results in Oracle and postgres for same outer join
> queries. Here are the details.
> 
> I have the following tables in our pg db
> 
> table: yuva_test1
> yt1_id        yt1_name    yt1_descr
> 1        1-name1    1-desc1
> 2        1-name2    1-desc2
> 3        1-name3    1-desc3
> 4        1-name4    1-desc4
> 5        1-name5    1-desc5
> 6        1-name6    1-desc6
> 
> table: yuva_test2
> yt2_id        yt2_name    yt2_descr
> 2        2-name2    2-desc2
> 3        2-name3    2-desc3
> 4        2-name4    2-desc4
> 
> When I run the query "select yt1_name, yt1_descr, yt2_name, yt2_descr from
> yuva_test1 left outer join yuva_test2 on yt1_id=yt2_id and yt2_name =
> '2-name2'" on postgres database I get the following results
> 
> yt1_name    yt1_descr    yt2_name    yt2_descr
> 1-name1    1-descr1
> 1-name2    1-descr2    2-name2    2-descr2
> 1-name3    1-descr3
> 1-name4    1-descr4
> 1-name5    1-descr5
> 1-name6    1-descr6
> 
> But when I tried the same on Oracle(8.1.7) (the query is "select yt1_name,
> yt1_descr, yt2_name, yt2_descr from yuva_test1, yuva_test2 where
> yt1_id=yt2_id(+) and yt2_name = '2-name2'') I get the following results
> 
> yt1_name    yt1_descr    yt2_name    yt2_descr
> 1-name2    1-descr2    2-name2    2-descr2
> 
> Why postgres is giving? which is standard? is it a bug? or is it the way
> postgres is implemented? Could some one help me?
> 
> Note: at the end of my mail is script to create tables and data in
> postgres.
> 
> Thanks
> Yuva
> Sr. Java Developer
> www.ebates.com
> 
> ============================================================
> Scripts:
> CREATE TABLE "yuva_test1" (
>   "yt1_id" numeric(16, 0), 
>   "yt1_name" varchar(16) NOT NULL, 
>   "yt1_descr" varchar(32)
> ) WITH OIDS;
> 
> CREATE TABLE "yuva_test2" (
>   "yt2_id" numeric(16, 0), 
>   "yt2_name" varchar(16) NOT NULL, 
>   "yt2_descr" varchar(32)
> ) WITH OIDS;
> 
> insert into yuva_test1 (yt1_id, yt1_name, yt1_descr) values (1, '1-name1',
> '1-descr1');
> insert into yuva_test1 (yt1_id, yt1_name, yt1_descr) values (2, '1-name2',
> '1-descr2');
> insert into yuva_test1 (yt1_id, yt1_name, yt1_descr) values (3, '1-name3',
> '1-descr3');
> insert into yuva_test1 (yt1_id, yt1_name, yt1_descr) values (4, '1-name4',
> '1-descr4');
> insert into yuva_test1 (yt1_id, yt1_name, yt1_descr) values (5, '1-name5',
> '1-descr5');
> insert into yuva_test1 (yt1_id, yt1_name, yt1_descr) values (6, '1-name6',
> '1-descr6');
> 
> insert into yuva_test2 (yt2_id, yt2_name, yt2_descr) values (2, '2-name2',
> '2-descr2');
> insert into yuva_test2 (yt2_id, yt2_name, yt2_descr) values (3, '2-name3',
> '2-descr3');
> insert into yuva_test2 (yt2_id, yt2_name, yt2_descr) values (4, '2-name4',
> '2-descr4');
> ============================================================