Thread: Outer Joins

Outer Joins

From
Michael Dunn
Date:
I am relatively new to the list and somewhat new to PostgreSQL.  I am
wondering if there has been any discussion or thought about including
outer joins in later releases of PostreSQL.  It seems highly inefficient
simulating outer joins with subqueries and UNION ALL statements.  Or,
perhaps PostgreSQL has another way prevent unjoined rows from being
supressed in the results.  Your comments are welcome.

Thanks, Micael Dunn


Re: Outer Joins

From
"Poul L. Christiansen"
Date:
PostgreSQL 7.1 (which is in beta now) will have outer joins.

It will probably (and hopefully) be released in Jan./Feb., but the beta
seems quite stable to me.

Poul L. Christiansen

Michael Dunn wrote:

> I am relatively new to the list and somewhat new to PostgreSQL.  I am
> wondering if there has been any discussion or thought about including
> outer joins in later releases of PostreSQL.  It seems highly inefficient
> simulating outer joins with subqueries and UNION ALL statements.  Or,
> perhaps PostgreSQL has another way prevent unjoined rows from being
> supressed in the results.  Your comments are welcome.
>
> Thanks, Micael Dunn


Automatic on-line replication

From
"Gordan Bobic"
Date:
Does postgres include this feature? Can someone point me toward the docs?

This is regarding the old clustering thread. If the on-line replication is
implemented, then it could be used for a form of clustering, because the
SELECTs could be distributed across multiple servers (one on each server).
Obviously, this would require the complete database to be on each server,
but until more advanced clustering methods are implemented, I don't see
another sensible way of doing clustering for situations where one server
just cannot feasibly cut it. Besides, insuring completeness of the returned
results when doing a multi-table join across multiple servers is a mind
numbingly hard problem...

I am also guessing that record locking would not work properly if multiple
computers were accessing the same physical database file that is mounted on
a remote file system. Is this the case? Not that I am even thinking about
trying to access data files via NFS or DFS... ;-)

Regards.

Gordan


Re: Outer Joins

From
"Robert B. Easter"
Date:
What is the syntax for this?  Is there an example I can see/run?

On Thursday 04 January 2001 04:30, Poul L. Christiansen wrote:
> PostgreSQL 7.1 (which is in beta now) will have outer joins.
>
> It will probably (and hopefully) be released in Jan./Feb., but the beta
> seems quite stable to me.
>
> Poul L. Christiansen
>
> Michael Dunn wrote:
> > I am relatively new to the list and somewhat new to PostgreSQL.  I am
> > wondering if there has been any discussion or thought about including
> > outer joins in later releases of PostreSQL.  It seems highly inefficient
> > simulating outer joins with subqueries and UNION ALL statements.  Or,
> > perhaps PostgreSQL has another way prevent unjoined rows from being
> > supressed in the results.  Your comments are welcome.
> >
> > Thanks, Micael Dunn

--
-------- Robert B. Easter  reaster@comptechnews.com ---------
-- CompTechNews Message Board http://www.comptechnews.com/ --
-- CompTechServ Tech Services http://www.comptechserv.com/ --
---------- http://www.comptechnews.com/~reaster/ ------------

Re: Outer Joins

From
Tom Lane
Date:
"Robert B. Easter" <reaster@comptechnews.com> writes:
> What is the syntax for this?  Is there an example I can see/run?

SQL92 standard.

See
http://www.postgresql.org/devel-corner/docs/postgres/sql-select.htm
for documentation (such as it is).  There are some examples in the
join regression test, too.

            regards, tom lane

Re: Outer Joins

From
"Brett W. McCoy"
Date:
On Sat, 6 Jan 2001, Robert B. Easter wrote:

> What is the syntax for this?  Is there an example I can see/run?

Should follow standard SQL92 syntax (which, BTW, Oralce doesn't):

SELECT * FROM table1 LEFT OUTER JOIN table2 ON (table1.field =
table2.field)

This will return all rows from table1 even if no corresponding row exists
in table2.  A RIGHT OUTER JOIN would do the opposite.

-- Brett
                                     http://www.chapelperilous.net/~bmccoy/
---------------------------------------------------------------------------
It is better to have loved a short man than never to have loved a tall.


Re: Outer Joins

From
"Robert B. Easter"
Date:
On Saturday 06 January 2001 20:21, Tom Lane wrote:
> "Robert B. Easter" <reaster@comptechnews.com> writes:
> > What is the syntax for this?  Is there an example I can see/run?
>
> SQL92 standard.
>
> See
> http://www.postgresql.org/devel-corner/docs/postgres/sql-select.htm
> for documentation (such as it is).  There are some examples in the
> join regression test, too.
>
>             regards, tom lane

Thanks. I've tested out the cvs version and see that these joins appear to
work:

Qualified join:
T1 INNER|[LEFT|RIGHT|FULL OUTER] JOIN T2 ON|USING() ...

Natural join:
T1 NATURAL INNER|[LEFT|RIGHT|FULL OUTER] JOIN T2

Cross join:
T1 CROSS JOIN T2

But,

Union join:
T1 UNION JOIN T2

is not implemented.  Nice! :)


Here is a sample running of all this on cvs pgsql:

CREATE TABLE a (id INTEGER, name TEXT, aname TEXT);
CREATE TABLE b (id INTEGER, name TEXT, bname TEXT);
CREATE TABLE c (id INTEGER, name TEXT, cname TEXT, date DATE DEFAULT
CURRENT_DATE);

INSERT INTO a VALUES (1, 'Bob', 'aname1');
INSERT INTO a VALUES (2, 'Jim', 'aname2');
INSERT INTO a VALUES (3, 'Tom', 'aname3');
INSERT INTO a VALUES (7, 'Joe', 'aname7');
INSERT INTO a VALUES (8, null, 'aname8');

INSERT INTO b VALUES (1, 'Bob', 'bname1');
INSERT INTO b VALUES (2, 'Tom', 'bname2');
INSERT INTO b VALUES (3, 'Joe', 'bname3');
INSERT INTO b VALUES (5, 'Jim', 'bname5');
INSERT INTO b VALUES (6, null, 'bname6');

INSERT INTO c VALUES (1, 'Bob', 'cname1');
INSERT INTO c VALUES (2, 'Jim', 'cname2');
INSERT INTO c VALUES (9, 'Tom', 'cname9');
INSERT INTO c VALUES (10, null, 'cname10');

-- Qualified Joins
SELECT * FROM a JOIN b USING (id) JOIN c USING (id);
SELECT * FROM a INNER JOIN b ON (a.id = b.id);
SELECT * FROM a LEFT OUTER JOIN b USING(id, name);
SELECT * FROM a RIGHT OUTER JOIN b USING (id);
SELECT * FROM a FULL OUTER JOIN b USING (id)
    RIGHT OUTER JOIN c USING(id);
-- Natural Joins
SELECT * FROM a NATURAL INNER JOIN b;
SELECT * FROM a NATURAL LEFT OUTER JOIN b;
SELECT * FROM a NATURAL RIGHT OUTER JOIN b;
SELECT * FROM a NATURAL FULL OUTER JOIN b;
-- Cross Join
SELECT * FROM a CROSS JOIN b;
-- Union Join (not implemented, yet)
SELECT * FROM a UNION JOIN b;


The output is like this with cvs version:
--------------------------------------------------------

CREATE TABLE a (id INTEGER, name TEXT, aname TEXT);
CREATE
CREATE TABLE b (id INTEGER, name TEXT, bname TEXT);
CREATE
CREATE TABLE c (id INTEGER, name TEXT, cname TEXT, date DATE DEFAULT
CURRENT_DATE);
CREATE
INSERT INTO a VALUES (1, 'Bob', 'aname1');
INSERT 21117 1
INSERT INTO a VALUES (2, 'Jim', 'aname2');
INSERT 21118 1
INSERT INTO a VALUES (3, 'Tom', 'aname3');
INSERT 21118 1
INSERT INTO a VALUES (7, 'Joe', 'aname7');
INSERT 21119 1
INSERT INTO a VALUES (8, null, 'aname8');
INSERT 21120 1

INSERT INTO b VALUES (1, 'Bob', 'bname1');
INSERT 21121 1
INSERT INTO b VALUES (2, 'Tom', 'bname2');
INSERT 21122 1
INSERT INTO b VALUES (3, 'Joe', 'bname3');
INSERT 21122 1
INSERT INTO b VALUES (5, 'Jim', 'bname5');
INSERT 21122 1
INSERT INTO b VALUES (6, null, 'bname6');
INSERT 21123 1

INSERT INTO c VALUES (1, 'Bob', 'cname1');
INSERT 21124 1
INSERT INTO c VALUES (2, 'Jim', 'cname2');
INSERT 21125 1
INSERT INTO c VALUES (9, 'Tom', 'cname9');
INSERT 21126 1
INSERT INTO c VALUES (10, null, 'cname10');
INSERT 21127 1

SELECT * FROM a JOIN b USING (id) JOIN c USING (id);

 id | name | aname  | name | bname  | name | cname  |    date
----+------+--------+------+--------+------+--------+------------
  1 | Bob  | aname1 | Bob  | bname1 | Bob  | cname1 | 2001-01-07
  2 | Jim  | aname2 | Tom  | bname2 | Jim  | cname2 | 2001-01-07
(2 rows)

SELECT * FROM a INNER JOIN b ON (a.id = b.id);

 id | name | aname  | id | name | bname
----+------+--------+----+------+--------
  1 | Bob  | aname1 |  1 | Bob  | bname1
  2 | Jim  | aname2 |  2 | Tom  | bname2
  3 | Tom  | aname3 |  3 | Joe  | bname3
(3 rows)

SELECT * FROM a LEFT OUTER JOIN b USING(id, name);

 id | name | aname  | bname
----+------+--------+--------
  1 | Bob  | aname1 | bname1
  2 | Jim  | aname2 |
  3 | Tom  | aname3 |
  7 | Joe  | aname7 |
  8 |      | aname8 |
(5 rows)

SELECT * FROM a RIGHT OUTER JOIN b USING (id);

 id | name | aname  | name | bname
----+------+--------+------+--------
  1 | Bob  | aname1 | Bob  | bname1
  2 | Jim  | aname2 | Tom  | bname2
  3 | Tom  | aname3 | Joe  | bname3
  5 |      |        | Jim  | bname5
  6 |      |        |      | bname6
(5 rows)

SELECT * FROM a FULL OUTER JOIN b USING (id)

 id | name | aname  | name | bname  | name |  cname  |    date
----+------+--------+------+--------+------+---------+------------
  1 | Bob  | aname1 | Bob  | bname1 | Bob  | cname1  | 2001-01-07
  2 | Jim  | aname2 | Tom  | bname2 | Jim  | cname2  | 2001-01-07
  9 |      |        |      |        | Tom  | cname9  | 2001-01-07
 10 |      |        |      |        |      | cname10 | 2001-01-07
(4 rows)

SELECT * FROM a NATURAL INNER JOIN b;

 id | name | aname  | bname
----+------+--------+--------
  1 | Bob  | aname1 | bname1
(1 row)

SELECT * FROM a NATURAL LEFT OUTER JOIN b;

 id | name | aname  | bname
----+------+--------+--------
  1 | Bob  | aname1 | bname1
  2 | Jim  | aname2 |
  3 | Tom  | aname3 |
  7 | Joe  | aname7 |
  8 |      | aname8 |
(5 rows)

SELECT * FROM a NATURAL RIGHT OUTER JOIN b;

 id | name | aname  | bname
----+------+--------+--------
  1 | Bob  | aname1 | bname1
  2 | Tom  |        | bname2
  3 | Joe  |        | bname3
  5 | Jim  |        | bname5
  6 |      |        | bname6
(5 rows)

SELECT * FROM a NATURAL FULL OUTER JOIN b;

 id | name | aname  | bname
----+------+--------+--------
  1 | Bob  | aname1 | bname1
  2 | Jim  | aname2 |
  2 | Tom  |        | bname2
  3 | Joe  |        | bname3
  3 | Tom  | aname3 |
  5 | Jim  |        | bname5
  6 |      |        | bname6
  7 | Joe  | aname7 |
  8 |      | aname8 |
(9 rows)

SELECT * FROM a CROSS JOIN b;

 id | name | aname  | id | name | bname
----+------+--------+----+------+--------
  1 | Bob  | aname1 |  1 | Bob  | bname1
  1 | Bob  | aname1 |  2 | Tom  | bname2
  1 | Bob  | aname1 |  3 | Joe  | bname3
  1 | Bob  | aname1 |  5 | Jim  | bname5
  1 | Bob  | aname1 |  6 |      | bname6
  2 | Jim  | aname2 |  1 | Bob  | bname1
  2 | Jim  | aname2 |  2 | Tom  | bname2
  2 | Jim  | aname2 |  3 | Joe  | bname3
  2 | Jim  | aname2 |  5 | Jim  | bname5
  2 | Jim  | aname2 |  6 |      | bname6
  3 | Tom  | aname3 |  1 | Bob  | bname1
  3 | Tom  | aname3 |  2 | Tom  | bname2
  3 | Tom  | aname3 |  3 | Joe  | bname3
  3 | Tom  | aname3 |  5 | Jim  | bname5
  3 | Tom  | aname3 |  6 |      | bname6
  7 | Joe  | aname7 |  1 | Bob  | bname1
  7 | Joe  | aname7 |  2 | Tom  | bname2
  7 | Joe  | aname7 |  3 | Joe  | bname3
  7 | Joe  | aname7 |  5 | Jim  | bname5
  7 | Joe  | aname7 |  6 |      | bname6
  8 |      | aname8 |  1 | Bob  | bname1
  8 |      | aname8 |  2 | Tom  | bname2
  8 |      | aname8 |  3 | Joe  | bname3
  8 |      | aname8 |  5 | Jim  | bname5
  8 |      | aname8 |  6 |      | bname6
(25 rows)

SELECT * FROM a UNION JOIN b;

ERROR:  UNION JOIN is not implemented yet
psql:/home/reaster/sql/join/join.sql:37: ERROR:  UNION JOIN is not
implemented yet
--------------------------------------------------------


Just for the heck of it, I tried to execute all this sql on 7.0.3 and got
this:

jointest=# \i join2.sql
CREATE
CREATE
CREATE
INSERT 2836025 1
INSERT 2836026 1
INSERT 2836027 1
INSERT 2836028 1
INSERT 2836029 1
INSERT 2836030 1
INSERT 2836031 1
INSERT 2836032 1
INSERT 2836033 1
INSERT 2836034 1
INSERT 2836035 1
INSERT 2836036 1
INSERT 2836037 1
INSERT 2836038 1
psql:join2.sql:23: pqReadData() -- backend closed the channel unexpectedly.
        This probably means the backend terminated abnormally
        before or while processing the request.
psql:join2.sql:23: connection to server was lost


I knew it wouldn't run it, but didn't think it would crash.

--
-------- Robert B. Easter  reaster@comptechnews.com ---------
-- CompTechNews Message Board http://www.comptechnews.com/ --
-- CompTechServ Tech Services http://www.comptechserv.com/ --
---------- http://www.comptechnews.com/~reaster/ ------------

Re: Outer Joins

From
"Robert B. Easter"
Date:
On Sunday 07 January 2001 00:53, Robert B. Easter wrote:
> Union join:
> T1 UNION JOIN T2
>
> is not implemented.  Nice! :)

[snip]

> SELECT * FROM a UNION JOIN b;
>
> ERROR:  UNION JOIN is not implemented yet
> psql:/home/reaster/sql/join/join.sql:37: ERROR:  UNION JOIN is not
> implemented yet


UNION JOIN is deprecated so maybe it doesn't need to be implemented?


--
-------- Robert B. Easter  reaster@comptechnews.com ---------
-- CompTechNews Message Board http://www.comptechnews.com/ --
-- CompTechServ Tech Services http://www.comptechserv.com/ --
---------- http://www.comptechnews.com/~reaster/ ------------

Re: Outer Joins

From
Tom Lane
Date:
"Robert B. Easter" <reaster@comptechnews.com> writes:
> Just for the heck of it, I tried to execute all this sql on 7.0.3 and got
> this:
> psql:join2.sql:23: pqReadData() -- backend closed the channel unexpectedly.
> I knew it wouldn't run it, but didn't think it would crash.

7.0 had the beginnings of parser support for JOIN syntax, but there
were bugs ... I think the one that you hit had to do with nested JOIN
clauses, ie, a JOIN b JOIN c.

            regards, tom lane

Re: Outer Joins

From
Tom Lane
Date:
"Robert B. Easter" <reaster@comptechnews.com> writes:
> UNION JOIN is deprecated

Oh?  By whom?

The reason 7.1 doesn't have it is I didn't have time for it, not that
we don't plan to do it ever.

            regards, tom lane

Re: Outer Joins

From
"Robert B. Easter"
Date:
On Sunday 07 January 2001 13:13, Tom Lane wrote:
> "Robert B. Easter" <reaster@comptechnews.com> writes:
> > UNION JOIN is deprecated
>
> Oh?  By whom?
>
> The reason 7.1 doesn't have it is I didn't have time for it, not that
> we don't plan to do it ever.

I read it in the SQL spec.  ANSI/ISO 9075-2 1999 (final).

                                       Annex D

                                    (informative)

                                 Deprecated features



         It is intended that the following features will be removed at a
         later date from a revised version of this part of ISO/IEC 9075:

         1) The ability to specify UNION JOIN in a <joined table> has been
            deprecated.

It's the only one.  I sent a patch to the patches list for JOIN
documentation.  In it, the only thing I said about UNION JOIN is
"Deprecated."  Let me know if I should change that.  I thought about omitting
it entirely.

--
-------- Robert B. Easter  reaster@comptechnews.com ---------
-- CompTechNews Message Board http://www.comptechnews.com/ --
-- CompTechServ Tech Services http://www.comptechserv.com/ --
---------- http://www.comptechnews.com/~reaster/ ------------

Re: Outer Joins

From
Tom Lane
Date:
"Robert B. Easter" <reaster@comptechnews.com> writes:
>>>> UNION JOIN is deprecated
>>
>> Oh?  By whom?

> I read it in the SQL spec.  ANSI/ISO 9075-2 1999 (final).

>          It is intended that the following features will be removed at a
>          later date from a revised version of this part of ISO/IEC 9075:
>          1) The ability to specify UNION JOIN in a <joined table> has been
>             deprecated.

Interesting.  Maybe we won't ever bother to do it, then.

            regards, tom lane

Another optimizer question

From
"Gordan Bobic"
Date:
I am not sure if this is a bug, an oversight or something else entirely,
but it would appear that if there are two tables, Table1 and Table2, which
are joined using INNER JOIN, specifying WHERE =  one of the join fields
doesn't automatically get equalised to the other field.

For example:

SELECT * FROM Table1 INNER JOIN Table2 ON (Table1.Field1 = Table2.Field1)
WHERE Table1.Field1 = 'SomeValue';

takes a very long time (several minutes), and explain says that sequential
scans are used on both tables.

However, changing the above to:

SELECT * FROM Table1 INNER JOIN Table2 ON (Table1.Field1 = Table2.Field1)
WHERE Table1.Field1 = 'SomeValue' AND Table2.Field1 = 'SomeValue';

yields the correct answer in a fraction of a second. Explain says that
indices are being used. However, here's a REALLY strange thing. If I do:

SET ENABLE_SEQSCAN = OFF;

and run the first query, explain says that indices are used, but it STILL
takes forever. The first, slow query executes a merge join, while the
second only executes two index scans in a nested loop.

Why? This seems like a fairly basic thing, but it seems to break something
in the way the query is executed...

Regards.

Gordan


Re: Another optimizer question

From
Tom Lane
Date:
"Gordan Bobic" <gordan@freeuk.com> writes:
> SELECT * FROM Table1 INNER JOIN Table2 ON (Table1.Field1 = Table2.Field1)
> WHERE Table1.Field1 = 'SomeValue';
> [ is slow, but this is fast: ]
> SELECT * FROM Table1 INNER JOIN Table2 ON (Table1.Field1 = Table2.Field1)
> WHERE Table1.Field1 = 'SomeValue' AND Table2.Field1 = 'SomeValue';

You're correct, we do not deduce the latter from the former, and so the
first example does not realize that it could use a constrained indexscan
over Table2.

Maybe we should try to do this, but I suspect we'd waste more cycles
trying than we'd make back on the queries where it helps.

            regards, tom lane

Re: Another optimizer question

From
"Gordan Bobic"
Date:
> > SELECT * FROM Table1 INNER JOIN Table2 ON (Table1.Field1 =
> > Table2.Field1)
> > WHERE Table1.Field1 = 'SomeValue';
> > [ is slow, but this is fast: ]
> > SELECT * FROM Table1 INNER JOIN Table2 ON (Table1.Field1 =
> > Table2.Field1)
> > WHERE Table1.Field1 = 'SomeValue' AND Table2.Field1 = 'SomeValue';
>
> You're correct, we do not deduce the latter from the former, and so the
> first example does not realize that it could use a constrained indexscan
> over Table2.
>
> Maybe we should try to do this, but I suspect we'd waste more cycles
> trying than we'd make back on the queries where it helps.

Hmm... As far as I can tell, it would help in any query joining several
tables on the same field in one table. I don't know how this compares to an
"average" case, but it is certainly common in the databases that I'm
working on... It would be nice if there was at least an option to enable
this sort of behaviour.

At the moment, the 6 table joins I am doing are so painfully slow, no
matter how I optimize the queries/views that I am going to forget about the
whole idea of views and set up some code that will do the separate table
subqueries manually. Even with _ALL_ fields that joins are performed on are
indexed in hash or btree, it still takes forever. Seen as I have to do this
often, unless I can find a way to speed up my queries by an order of
magnitude (or several in some cases), I don't see any other way around
this.

If I do a view that produces the data I want through joins, it takes hours,
even with all fields indexed, and after VACUUM ANALYZE. Doing SET ENABLE
SEQ_SCAN = OFF doesn't seem to make any difference. The query plan changes,
but select times are still roughly the same... Doing the separate
subqueries on each table and joining data manualy in the application code
takes literaly seconds. I am sure that cannot be right and I must be doing
something wrong, so if anyone has a good idea of how to solve this type of
problem, I'm not sure I have a lot of options left...

Regards.

Gordan


Re: Another optimizer question

From
Tom Lane
Date:
"Gordan Bobic" <gordan@freeuk.com> writes:
> If I do a view that produces the data I want through joins, it takes hours,
> even with all fields indexed, and after VACUUM ANALYZE. Doing SET ENABLE
> SEQ_SCAN = OFF doesn't seem to make any difference. The query plan changes,
> but select times are still roughly the same... Doing the separate
> subqueries on each table and joining data manualy in the application code
> takes literaly seconds.

Um, have you updated since I changed the subselect-restriction
processing two days ago?

            regards, tom lane

Re: Another optimizer question

From
"Gordan Bobic"
Date:
> > If I do a view that produces the data I want through joins, it takes
hours,
> > even with all fields indexed, and after VACUUM ANALYZE. Doing SET
ENABLE
> > SEQ_SCAN = OFF doesn't seem to make any difference. The query plan
changes,
> > but select times are still roughly the same... Doing the separate
> > subqueries on each table and joining data manualy in the application
code
> > takes literaly seconds.
>
> Um, have you updated since I changed the subselect-restriction
> processing two days ago?

Not yet. I've done it in appliction code for now. I'll try again in
straight SQL when the next beta or release are available.

Thanks.

Gordan


Re: Outer Joins

From
Bruce Momjian
Date:
Can someone explain why cname and date from table c gets printed in this
query?

Thanks.

> SELECT * FROM a FULL OUTER JOIN b USING (id)
>
>  id | name | aname  | name | bname  | name |  cname  |    date
> ----+------+--------+------+--------+------+---------+------------
>   1 | Bob  | aname1 | Bob  | bname1 | Bob  | cname1  | 2001-01-07
>   2 | Jim  | aname2 | Tom  | bname2 | Jim  | cname2  | 2001-01-07
>   9 |      |        |      |        | Tom  | cname9  | 2001-01-07
>  10 |      |        |      |        |      | cname10 | 2001-01-07
> (4 rows)
>

---------------------------------------------------------------------------


[ Charset ISO-8859-1 unsupported, converting... ]
> On Saturday 06 January 2001 20:21, Tom Lane wrote:
> > "Robert B. Easter" <reaster@comptechnews.com> writes:
> > > What is the syntax for this?  Is there an example I can see/run?
> >
> > SQL92 standard.
> >
> > See
> > http://www.postgresql.org/devel-corner/docs/postgres/sql-select.htm
> > for documentation (such as it is).  There are some examples in the
> > join regression test, too.
> >
> >             regards, tom lane
>
> Thanks. I've tested out the cvs version and see that these joins appear to
> work:
>
> Qualified join:
> T1 INNER|[LEFT|RIGHT|FULL OUTER] JOIN T2 ON|USING() ...
>
> Natural join:
> T1 NATURAL INNER|[LEFT|RIGHT|FULL OUTER] JOIN T2
>
> Cross join:
> T1 CROSS JOIN T2
>
> But,
>
> Union join:
> T1 UNION JOIN T2
>
> is not implemented.  Nice! :)
>
>
> Here is a sample running of all this on cvs pgsql:
>
> CREATE TABLE a (id INTEGER, name TEXT, aname TEXT);
> CREATE TABLE b (id INTEGER, name TEXT, bname TEXT);
> CREATE TABLE c (id INTEGER, name TEXT, cname TEXT, date DATE DEFAULT
> CURRENT_DATE);
>
> INSERT INTO a VALUES (1, 'Bob', 'aname1');
> INSERT INTO a VALUES (2, 'Jim', 'aname2');
> INSERT INTO a VALUES (3, 'Tom', 'aname3');
> INSERT INTO a VALUES (7, 'Joe', 'aname7');
> INSERT INTO a VALUES (8, null, 'aname8');
>
> INSERT INTO b VALUES (1, 'Bob', 'bname1');
> INSERT INTO b VALUES (2, 'Tom', 'bname2');
> INSERT INTO b VALUES (3, 'Joe', 'bname3');
> INSERT INTO b VALUES (5, 'Jim', 'bname5');
> INSERT INTO b VALUES (6, null, 'bname6');
>
> INSERT INTO c VALUES (1, 'Bob', 'cname1');
> INSERT INTO c VALUES (2, 'Jim', 'cname2');
> INSERT INTO c VALUES (9, 'Tom', 'cname9');
> INSERT INTO c VALUES (10, null, 'cname10');
>
> -- Qualified Joins
> SELECT * FROM a JOIN b USING (id) JOIN c USING (id);
> SELECT * FROM a INNER JOIN b ON (a.id = b.id);
> SELECT * FROM a LEFT OUTER JOIN b USING(id, name);
> SELECT * FROM a RIGHT OUTER JOIN b USING (id);
> SELECT * FROM a FULL OUTER JOIN b USING (id)
>     RIGHT OUTER JOIN c USING(id);
> -- Natural Joins
> SELECT * FROM a NATURAL INNER JOIN b;
> SELECT * FROM a NATURAL LEFT OUTER JOIN b;
> SELECT * FROM a NATURAL RIGHT OUTER JOIN b;
> SELECT * FROM a NATURAL FULL OUTER JOIN b;
> -- Cross Join
> SELECT * FROM a CROSS JOIN b;
> -- Union Join (not implemented, yet)
> SELECT * FROM a UNION JOIN b;
>
>
> The output is like this with cvs version:
> --------------------------------------------------------
>
> CREATE TABLE a (id INTEGER, name TEXT, aname TEXT);
> CREATE
> CREATE TABLE b (id INTEGER, name TEXT, bname TEXT);
> CREATE
> CREATE TABLE c (id INTEGER, name TEXT, cname TEXT, date DATE DEFAULT
> CURRENT_DATE);
> CREATE
> INSERT INTO a VALUES (1, 'Bob', 'aname1');
> INSERT 21117 1
> INSERT INTO a VALUES (2, 'Jim', 'aname2');
> INSERT 21118 1
> INSERT INTO a VALUES (3, 'Tom', 'aname3');
> INSERT 21118 1
> INSERT INTO a VALUES (7, 'Joe', 'aname7');
> INSERT 21119 1
> INSERT INTO a VALUES (8, null, 'aname8');
> INSERT 21120 1
>
> INSERT INTO b VALUES (1, 'Bob', 'bname1');
> INSERT 21121 1
> INSERT INTO b VALUES (2, 'Tom', 'bname2');
> INSERT 21122 1
> INSERT INTO b VALUES (3, 'Joe', 'bname3');
> INSERT 21122 1
> INSERT INTO b VALUES (5, 'Jim', 'bname5');
> INSERT 21122 1
> INSERT INTO b VALUES (6, null, 'bname6');
> INSERT 21123 1
>
> INSERT INTO c VALUES (1, 'Bob', 'cname1');
> INSERT 21124 1
> INSERT INTO c VALUES (2, 'Jim', 'cname2');
> INSERT 21125 1
> INSERT INTO c VALUES (9, 'Tom', 'cname9');
> INSERT 21126 1
> INSERT INTO c VALUES (10, null, 'cname10');
> INSERT 21127 1
>
> SELECT * FROM a JOIN b USING (id) JOIN c USING (id);
>
>  id | name | aname  | name | bname  | name | cname  |    date
> ----+------+--------+------+--------+------+--------+------------
>   1 | Bob  | aname1 | Bob  | bname1 | Bob  | cname1 | 2001-01-07
>   2 | Jim  | aname2 | Tom  | bname2 | Jim  | cname2 | 2001-01-07
> (2 rows)
>
> SELECT * FROM a INNER JOIN b ON (a.id = b.id);
>
>  id | name | aname  | id | name | bname
> ----+------+--------+----+------+--------
>   1 | Bob  | aname1 |  1 | Bob  | bname1
>   2 | Jim  | aname2 |  2 | Tom  | bname2
>   3 | Tom  | aname3 |  3 | Joe  | bname3
> (3 rows)
>
> SELECT * FROM a LEFT OUTER JOIN b USING(id, name);
>
>  id | name | aname  | bname
> ----+------+--------+--------
>   1 | Bob  | aname1 | bname1
>   2 | Jim  | aname2 |
>   3 | Tom  | aname3 |
>   7 | Joe  | aname7 |
>   8 |      | aname8 |
> (5 rows)
>
> SELECT * FROM a RIGHT OUTER JOIN b USING (id);
>
>  id | name | aname  | name | bname
> ----+------+--------+------+--------
>   1 | Bob  | aname1 | Bob  | bname1
>   2 | Jim  | aname2 | Tom  | bname2
>   3 | Tom  | aname3 | Joe  | bname3
>   5 |      |        | Jim  | bname5
>   6 |      |        |      | bname6
> (5 rows)
>
> SELECT * FROM a FULL OUTER JOIN b USING (id)
>
>  id | name | aname  | name | bname  | name |  cname  |    date
> ----+------+--------+------+--------+------+---------+------------
>   1 | Bob  | aname1 | Bob  | bname1 | Bob  | cname1  | 2001-01-07
>   2 | Jim  | aname2 | Tom  | bname2 | Jim  | cname2  | 2001-01-07
>   9 |      |        |      |        | Tom  | cname9  | 2001-01-07
>  10 |      |        |      |        |      | cname10 | 2001-01-07
> (4 rows)
>
> SELECT * FROM a NATURAL INNER JOIN b;
>
>  id | name | aname  | bname
> ----+------+--------+--------
>   1 | Bob  | aname1 | bname1
> (1 row)
>
> SELECT * FROM a NATURAL LEFT OUTER JOIN b;
>
>  id | name | aname  | bname
> ----+------+--------+--------
>   1 | Bob  | aname1 | bname1
>   2 | Jim  | aname2 |
>   3 | Tom  | aname3 |
>   7 | Joe  | aname7 |
>   8 |      | aname8 |
> (5 rows)
>
> SELECT * FROM a NATURAL RIGHT OUTER JOIN b;
>
>  id | name | aname  | bname
> ----+------+--------+--------
>   1 | Bob  | aname1 | bname1
>   2 | Tom  |        | bname2
>   3 | Joe  |        | bname3
>   5 | Jim  |        | bname5
>   6 |      |        | bname6
> (5 rows)
>
> SELECT * FROM a NATURAL FULL OUTER JOIN b;
>
>  id | name | aname  | bname
> ----+------+--------+--------
>   1 | Bob  | aname1 | bname1
>   2 | Jim  | aname2 |
>   2 | Tom  |        | bname2
>   3 | Joe  |        | bname3
>   3 | Tom  | aname3 |
>   5 | Jim  |        | bname5
>   6 |      |        | bname6
>   7 | Joe  | aname7 |
>   8 |      | aname8 |
> (9 rows)
>
> SELECT * FROM a CROSS JOIN b;
>
>  id | name | aname  | id | name | bname
> ----+------+--------+----+------+--------
>   1 | Bob  | aname1 |  1 | Bob  | bname1
>   1 | Bob  | aname1 |  2 | Tom  | bname2
>   1 | Bob  | aname1 |  3 | Joe  | bname3
>   1 | Bob  | aname1 |  5 | Jim  | bname5
>   1 | Bob  | aname1 |  6 |      | bname6
>   2 | Jim  | aname2 |  1 | Bob  | bname1
>   2 | Jim  | aname2 |  2 | Tom  | bname2
>   2 | Jim  | aname2 |  3 | Joe  | bname3
>   2 | Jim  | aname2 |  5 | Jim  | bname5
>   2 | Jim  | aname2 |  6 |      | bname6
>   3 | Tom  | aname3 |  1 | Bob  | bname1
>   3 | Tom  | aname3 |  2 | Tom  | bname2
>   3 | Tom  | aname3 |  3 | Joe  | bname3
>   3 | Tom  | aname3 |  5 | Jim  | bname5
>   3 | Tom  | aname3 |  6 |      | bname6
>   7 | Joe  | aname7 |  1 | Bob  | bname1
>   7 | Joe  | aname7 |  2 | Tom  | bname2
>   7 | Joe  | aname7 |  3 | Joe  | bname3
>   7 | Joe  | aname7 |  5 | Jim  | bname5
>   7 | Joe  | aname7 |  6 |      | bname6
>   8 |      | aname8 |  1 | Bob  | bname1
>   8 |      | aname8 |  2 | Tom  | bname2
>   8 |      | aname8 |  3 | Joe  | bname3
>   8 |      | aname8 |  5 | Jim  | bname5
>   8 |      | aname8 |  6 |      | bname6
> (25 rows)
>
> SELECT * FROM a UNION JOIN b;
>
> ERROR:  UNION JOIN is not implemented yet
> psql:/home/reaster/sql/join/join.sql:37: ERROR:  UNION JOIN is not
> implemented yet
> --------------------------------------------------------
>
>
> Just for the heck of it, I tried to execute all this sql on 7.0.3 and got
> this:
>
> jointest=# \i join2.sql
> CREATE
> CREATE
> CREATE
> INSERT 2836025 1
> INSERT 2836026 1
> INSERT 2836027 1
> INSERT 2836028 1
> INSERT 2836029 1
> INSERT 2836030 1
> INSERT 2836031 1
> INSERT 2836032 1
> INSERT 2836033 1
> INSERT 2836034 1
> INSERT 2836035 1
> INSERT 2836036 1
> INSERT 2836037 1
> INSERT 2836038 1
> psql:join2.sql:23: pqReadData() -- backend closed the channel unexpectedly.
>         This probably means the backend terminated abnormally
>         before or while processing the request.
> psql:join2.sql:23: connection to server was lost
>
>
> I knew it wouldn't run it, but didn't think it would crash.
>
> --
> -------- Robert B. Easter  reaster@comptechnews.com ---------
> -- CompTechNews Message Board http://www.comptechnews.com/ --
> -- CompTechServ Tech Services http://www.comptechserv.com/ --
> ---------- http://www.comptechnews.com/~reaster/ ------------
>


--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: Outer Joins

From
Tom Lane
Date:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> Can someone explain why cname and date from table c gets printed in this
> query?

Say what?

test=# CREATE TABLE a (id INTEGER, name TEXT, aname TEXT);
CREATE
test=# CREATE TABLE b (id INTEGER, name TEXT, bname TEXT);
CREATE
test=# CREATE TABLE c (id INTEGER, name TEXT, cname TEXT, date DATE DEFAULT
test(# CURRENT_DATE);
CREATE
test=# SELECT * FROM a FULL OUTER JOIN b USING (id);
 id | name | aname | name | bname
----+------+-------+------+-------
(0 rows)


            regards, tom lane

Re: Outer Joins

From
Bruce Momjian
Date:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> > Can someone explain why cname and date from table c gets printed in this
> > query?
>
> Say what?
>
> test=# CREATE TABLE a (id INTEGER, name TEXT, aname TEXT);
> CREATE
> test=# CREATE TABLE b (id INTEGER, name TEXT, bname TEXT);
> CREATE
> test=# CREATE TABLE c (id INTEGER, name TEXT, cname TEXT, date DATE DEFAULT
> test(# CURRENT_DATE);
> CREATE
> test=# SELECT * FROM a FULL OUTER JOIN b USING (id);
>  id | name | aname | name | bname
> ----+------+-------+------+-------
> (0 rows)

The text of the email showed this query returning columns from table c.
Seems it was just a mistake in the email.

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: Outer Joins

From
"Robert B. Easter"
Date:
On Tuesday 23 January 2001 11:30, Bruce Momjian wrote:
> Can someone explain why cname and date from table c gets printed in this
> query?

The query was supposed to be:

SELECT * FROM a FULL OUTER JOIN b USING (id)
������� RIGHT OUTER JOIN c USING(id);

I missed the end of it when I was writing the email.

> > SELECT * FROM a FULL OUTER JOIN b USING (id)  <-- no ';'

> >  id | name | aname  | name | bname  | name |  cname  |    date
> > ----+------+--------+------+--------+------+---------+------------
> >   1 | Bob  | aname1 | Bob  | bname1 | Bob  | cname1  | 2001-01-07
> >   2 | Jim  | aname2 | Tom  | bname2 | Jim  | cname2  | 2001-01-07
> >   9 |      |        |      |        | Tom  | cname9  | 2001-01-07
> >  10 |      |        |      |        |      | cname10 | 2001-01-07
> > (4 rows)
>
> ---------------------------------------------------------------------------
>

--
-------- Robert B. Easter  reaster@comptechnews.com ---------
-- CompTechNews Message Board http://www.comptechnews.com/ --
-- CompTechServ Tech Services http://www.comptechserv.com/ --
---------- http://www.comptechnews.com/~reaster/ ------------

JRelationalFramework

From
Erik Tennant
Date:
Has anybody used Postgres with JRelationalFramework
(http://jrf.sourceforge.net/)? Any opinions on it? I have been looking it
over, and it seems kind of interesting...

If someone has already written a DatabasePolicy Interface for Postgres,
could you post it?

Thanks,
Erik