Thread: (+) oracle notation
Hi I just discovered the (+) oracle join notation, is there something like this in postgres ? -- Mathieu Arnold
On Thu, 19 Oct 2000, Mathieu Arnold wrote: > I just discovered the (+) oracle join notation, is there something like > this in postgres ? That's the outer join operator for Oracle, right? I believe that outer joins are coming in 7.2, but I don't know if that means the operator will be (I don't think it's standard). Brett W. McCoy http://www.chapelperilous.net --------------------------------------------------------------------------- Don't let people drive you crazy when you know it's in walking distance.
<bmccoy@chapelperilous.net> writes: > On Thu, 19 Oct 2000, Mathieu Arnold wrote: > > > I just discovered the (+) oracle join notation, is there something like > > this in postgres ? > > That's the outer join operator for Oracle, right? I believe that outer > joins are coming in 7.2, but I don't know if that means the operator will > be (I don't think it's standard). What does the operator do? I know what an outer join does, but not where that operator comes into the picture. Tomas
On 19 Oct 2000, Tomas Berndtsson wrote: > > On Thu, 19 Oct 2000, Mathieu Arnold wrote: > > > > > I just discovered the (+) oracle join notation, is there something like > > > this in postgres ? > > > > That's the outer join operator for Oracle, right? I believe that outer > > joins are coming in 7.2, but I don't know if that means the operator will > > be (I don't think it's standard). > > What does the operator do? I know what an outer join does, but not > where that operator comes into the picture. It's used, in Oracle, like this: SELECT <fields> FROM <tables> WHERE table1.field (+) = table2.field; This will return all appropriate rows in table1, even if no corresponding value exists in table2 (it'll list an empty value for that column in the output tuples if no value exists). Oracle doesn't seem to use the OUTER JOIN keywords other databases use. You can also put the (+) after the second field to get all of the rows in the second table even if no value exists in the first table. I'm looking forward to having outer joins in PostgreSQL, (+) operator or not. It is the one feature, after foreign keys, that I had been missing in PostgreSQL for a couple of years now and am quite happy they are making into the next release. Brett W. McCoy http://www.chapelperilous.net --------------------------------------------------------------------------- I'll be Grateful when they're Dead.
On Thu, 19 Oct 2000 bmccoy@chapelperilous.net wrote: > > I just discovered the (+) oracle join notation, is there something like > > this in postgres ? > > That's the outer join operator for Oracle, right? I believe that outer > joins are coming in 7.2, but I don't know if that means the operator will > be (I don't think it's standard). Oops, I meant 7.1! Brett W. McCoy http://www.chapelperilous.net --------------------------------------------------------------------------- Love is staying up all night with a sick child, or a healthy adult.
Example of its use: select a.item_number, b.group_code_description from items a, group_codes b where a.group_code = b.group_code (+); in this example all the records in table "items" appear in the output and all those records in "group codes" that matches the group_code in items. The "group_code_description" of all those non-matching records in "group_codes" table are displayed as NULL. ----- Original Message ----- From: "Tomas Berndtsson" <tomas@nocrew.org> To: "pgsql-general" <pgsql-general@postgresql.org> Sent: Thursday, October 19, 2000 12:47 PM Subject: Re: [GENERAL] (+) oracle notation > <bmccoy@chapelperilous.net> writes: > > > On Thu, 19 Oct 2000, Mathieu Arnold wrote: > > > > > I just discovered the (+) oracle join notation, is there something like > > > this in postgres ? > > > > That's the outer join operator for Oracle, right? I believe that outer > > joins are coming in 7.2, but I don't know if that means the operator will > > be (I don't think it's standard). > > What does the operator do? I know what an outer join does, but not > where that operator comes into the picture. > > > Tomas >
> SELECT <fields> FROM <tables> WHERE table1.field (+) = table2.field; > > This will return all appropriate rows in table1, even if no > corresponding value exists in table2 (it'll list an empty value for that > column in the output tuples if no value exists). In order to do that you should put the (+) operator at the "possible nulls" side of the equality. It should go this way: SELECT <fields> FROM <tables> WHERE table1.field = table2.field (+);
There is an artifical way to do the outer join in PostgreSQL... It involves using UNION and NOT IN... see : http://www.postgresql.org/docs/aw_pgsql_book/node305.html Hope this helps... -jag -- "She who is wanting me, Whose touch can make me cry, I can only understand By never asking her why..." -John Popper
I'm not sure about the standard, but I really like Oracle's notation for foreign keys: select a.item_number, b.group_code_description from items a, group_codes b where a.group_code = b.group_code (+); Much better than select a.item_number, b.group_code_description from items a outer join group_codes b on a.group_code = b.group_code; In fact, it's MUCH BETTER when you have to join several tables (one thing PgSQL is very good at, by the way). In such cases, the seconde syntax requires an unreadable lot of ()'s in the from clause. Don't mean to throw away the standard though, but having Oracle's (+) syntax around too would be a big help.
"Edmar Wiggers" <edmar@brasmap.com> writes: > I'm not sure about the standard, but I really like Oracle's notation for > foreign keys: > select a.item_number, b.group_code_description > from items a, group_codes b > where a.group_code = b.group_code (+); I beg to differ --- IMHO, Oracle's notation is brain dead. If they had stuck the (+) markers on FROM-list items, it would have been sort of reasonable, but as is, it's incomplete and ambiguous. Incomplete because you can't specify an outer join against a table that's not referenced anywhere in the WHERE clause. Ambiguous because it's not clear what it means if you reference several columns from the same table in WHERE, and tag some of them with (+) and others not. Does that mean you get an outer join anyway? Is it an error condition? Maybe you should implicitly get two FROM-list items, one outer joined and one not? Worse, if you have more than two FROM-items it's very unclear what the Oracle syntax means at all. There is a big difference between (A CROSS JOIN B) LEFT JOIN C and A CROSS JOIN (B LEFT JOIN C) not to mention (A LEFT JOIN C) CROSS JOIN B but who is to say which of these behaviors you will get from, say, select ... from A, B, C where a1 = b1 and a2 = c2 (+) ? And if you reorder the terms in the WHERE, do you get a different answer? It gets a lot worse if more than one table is outer-joined. I don't have any great love for the ISO syntax either; it's certainly mighty verbose. But at least you can tell what the heck it means. regards, tom lane
Tom Lane wrote: > > "Edmar Wiggers" <edmar@brasmap.com> writes: > > I'm not sure about the standard, but I really like Oracle's notation for > > foreign keys: > > > select a.item_number, b.group_code_description > > from items a, group_codes b > > where a.group_code = b.group_code (+); > > I beg to differ --- IMHO, Oracle's notation is brain dead. I agree. In my opinion the best syntax for outer joins was brought up by informix. Ex: SELECT a.f1, b.f1, c.f1 FROM a, OUTER( b, OUTER c ) WHERE a.key = b.fkkey AND b.key = c.fkkey Where b is outer from a and c outer from b. Precedence and hierachical order is given by the parenthesis. Same example FROM a, OUTER ( b, c) b and c are outer from a. I find this syntax clear and logic without any danger of missinterpretation Best regards Herbie
Sorry, maybe I confused you. The Oracle way: I failed to mention that (+) are specific to outer joins. There is no way to express a join in the from clause. Everything goes on the where clause: joins and "filter conditions". In the where clause, it is common practice to express to specify first your joins and after your filters. Example: 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. When you are joining 8 tables, that syntax becomes clearer. 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.
Agreed. > Tom Lane wrote: > > > > "Edmar Wiggers" <edmar@brasmap.com> writes: > > > I'm not sure about the standard, but I really like Oracle's notation for > > > foreign keys: > > > > > select a.item_number, b.group_code_description > > > from items a, group_codes b > > > where a.group_code = b.group_code (+); > > > > I beg to differ --- IMHO, Oracle's notation is brain dead. > > I agree. In my opinion the best syntax for outer joins was brought up > by informix. Ex: > > SELECT a.f1, b.f1, c.f1 > FROM a, OUTER( b, OUTER c ) > WHERE a.key = b.fkkey > AND b.key = c.fkkey > > Where b is outer from a and c outer from b. Precedence and > hierachical order is given by the parenthesis. Same example > > FROM a, OUTER ( b, c) > > b and c are outer from a. I find this syntax clear and logic without > any danger of missinterpretation > > Best regards > Herbie > -- 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
"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
Got it. Thanks. Even though I'd never seen it like that, it is indeed ambiguous. In Oracle, > where > a.id = b.id(+) and > (b.weight > 10 OR b IS NULL); is equivalent to > ... FROM a LEFT JOIN b ON (a.id = b.id) WHERE b.weight > 10 That is, we get row 2,NULL,NULL. To produce > ... FROM a LEFT JOIN b ON (a.id = b.id AND b.weight > 10) you have to use "in-line views" (Oracle term), like ... FROM a, (select * from table_b where b.weight > 10) b WHERE a.id = b.id(+); I guess that finishes it. Let's use STANDARD syntax and that's it. I guess postgres would need a lot of massage on query parsing to get oracle's mysterious syntax right.
Hi, The Sybase notation for outer joins seems to be good too: *= or =* Claudio Edmar Wiggers wrote: > I'm not sure about the standard, but I really like Oracle's notation for > foreign keys: > > select a.item_number, b.group_code_description > from items a, group_codes b > where a.group_code = b.group_code (+); > > Much better than > > select a.item_number, b.group_code_description > from items a outer join group_codes b on a.group_code = b.group_code; > > In fact, it's MUCH BETTER when you have to join several tables (one thing > PgSQL is very good at, by the way). In such cases, the seconde syntax > requires an unreadable lot of ()'s in the from clause. > > Don't mean to throw away the standard though, but having Oracle's (+) syntax > around too would be a big help.
Excuse me, I should have written : I t seems to be ambiguous !!! too ... Claudio. Claudio Jose Zanardi Grillo wrote: > Hi, > > The Sybase notation for outer joins seems to be good too: > > *= > or > =* > > Claudio > > Edmar Wiggers wrote: > > > I'm not sure about the standard, but I really like Oracle's notation for > > foreign keys: > > > > select a.item_number, b.group_code_description > > from items a, group_codes b > > where a.group_code = b.group_code (+); > > > > Much better than > > > > select a.item_number, b.group_code_description > > from items a outer join group_codes b on a.group_code = b.group_code; > > > > In fact, it's MUCH BETTER when you have to join several tables (one thing > > PgSQL is very good at, by the way). In such cases, the seconde syntax > > requires an unreadable lot of ()'s in the from clause. > > > > Don't mean to throw away the standard though, but having Oracle's (+) syntax > > around too would be a big help.