Thread: Slightly OT: outer joins

Slightly OT: outer joins

From
Fran Fabrizio
Date:
This is a little off topic but this is the best source of SQL knowledge
I know about so hopefully this will be interesting enough for someone to
answer. :-)

I've got the following tables:

Table people
id    fname    lname
1     bob       smith
2     tom       jones
3     jane      doe
4     mike     porter

Table food
id    favorite_food
2     eggrolls
3     ice cream

Table color
id     color
1      red
3      blue

I want a query to produce the result set:

fname   lname   favorite_color  favorite_food
bob      smith     red               null
tom      jones     null              eggrolls
jane      doe       blue            ice cream
mike    porter     null             null

I'm having lots of trouble getting the right result or knowing whether
this is even a valid usage of outer joins.  Can somebody show me a
working query?  Thanks!

-Fran


Re: Slightly OT: outer joins

From
Risko Peter
Date:
On Tue, 20 Nov 2001, Fran Fabrizio wrote:
> This is a little off topic but this is the best source of SQL knowledge
> I know about so hopefully this will be interesting enough for someone to
> answer. :-)
> I've got the following tables:
> Table people
> id    fname    lname
> 1     bob       smith
> 2     tom       jones
> 3     jane      doe
> 4     mike     porter
> Table food
> id    favorite_food
> 2     eggrolls
> 3     ice cream
> Table color
> id     color
> 1      red
> 3      blue
> I want a query to produce the result set:
> fname   lname   favorite_color  favorite_food
> bob      smith     red               null
> tom      jones     null              eggrolls
> jane      doe       blue            ice cream
> mike    porter     null             null
> I'm having lots of trouble getting the right result or knowing whether
> this is even a valid usage of outer joins.  Can somebody show me a
> working query?  Thanks!
Hi Fran!

  I'm a beginner, and maybe I will misinform you, but I think in the above
case you want your tables being joined by the ID column. In that case you
_should_ have a row in your auxiliary tables (color, food) for every
occuring IDs in the main table. It will solve your problem:
---
drop table people;
drop table food;
drop table color;
create table people(id int4,fname char(10),lname char(10));
create table food(id int4,favorite_food char(10));
create table color(id int4,color char(10));
copy food from stdin;
1
2    eggrolls
3    ice cream
4
\.
copy color from stdin;
1    red
2
3    blue
4
\.
copy people from stdin;
1    bob    smith
2    tom    jones
3    jane    doe
4    mike    porter
\.
select fname,lname,color,favorite_food from people,food,color where
    people.id=food.id and people.id=color.id;


Udv: rpetike


Re: Slightly OT: outer joins

From
merlyn@stonehenge.com (Randal L. Schwartz)
Date:
>>>>> "Fran" == Fran Fabrizio <ffabrizio@mmrd.com> writes:

Fran> This is a little off topic but this is the best source of SQL knowledge
Fran> I know about so hopefully this will be interesting enough for someone to
Fran> answer. :-)

Fran> I've got the following tables:

Fran> Table people
Fran> id    fname    lname
Fran> 1     bob       smith
Fran> 2     tom       jones
Fran> 3     jane      doe
Fran> 4     mike     porter

Fran> Table food
Fran> id    favorite_food
Fran> 2     eggrolls
Fran> 3     ice cream

Fran> Table color
Fran> id     color
Fran> 1      red
Fran> 3      blue

Fran> I want a query to produce the result set:

Fran> fname   lname   favorite_color  favorite_food
Fran> bob      smith     red               null
Fran> tom      jones     null              eggrolls
Fran> jane      doe       blue            ice cream
Fran> mike    porter     null             null

Fran> I'm having lots of trouble getting the right result or knowing whether
Fran> this is even a valid usage of outer joins.  Can somebody show me a
Fran> working query?  Thanks!

Got it on the first try:

test=# select * from people natural left join color natural left join food;
 id | fname | lname  | color | favorite_food
----+-------+--------+-------+---------------
  1 | bob   | smith  | red   |
  2 | tom   | jones  |       | eggrolls
  3 | jane  | doe    | blue  | ice cream
  4 | mike  | porter |       |
(4 rows)

That's presuming "id" matches "id" in each table, thus the easy
use of the "natural" keyword.  The "left join" is what gives you
nulls on the right.

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!

Re: Slightly OT: outer joins

From
Brian Avis
Date:
I'm sort of a beginner myself so forgive me if this is wrong. But that solution sort of assumes that data is being put into the tables at the same time.

Wouldn't a better solution be to setup the first table like this.

people

------------------------------
|  id  |  fname  |  lname  |  food_id  |  color_id  |
------------------------------
|  1   |  bob       |  smith    |       2        |       3           |
------------------------------


Then you should be able to do a normal join type select and get the right results no matter what.


Risko Peter wrote:
On Tue, 20 Nov 2001, Fran Fabrizio wrote:
This is a little off topic but this is the best source of SQL knowledge
I know about so hopefully this will be interesting enough for someone to
answer. :-)
I've got the following tables:
Table people
id fname lname
1 bob smith
2 tom jones
3 jane doe
4 mike porter
Table food
id favorite_food
2 eggrolls
3 ice cream
Table color
id color
1 red
3 blue
I want a query to produce the result set:
fname lname favorite_color favorite_food
bob smith red null
tom jones null eggrolls
jane doe blue ice cream
mike porter null null
I'm having lots of trouble getting the right result or knowing whether
this is even a valid usage of outer joins. Can somebody show me a
working query? Thanks!
Hi Fran!

I'm a beginner, and maybe I will misinform you, but I think in the above
case you want your tables being joined by the ID column. In that case you
_should_ have a row in your auxiliary tables (color, food) for every
occuring IDs in the main table. It will solve your problem:
---
drop table people;
drop table food;
drop table color;
create table people(id int4,fname char(10),lname char(10));
create table food(id int4,favorite_food char(10));
create table color(id int4,color char(10));
copy food from stdin;
1
2 eggrolls
3 ice cream
4
\.
copy color from stdin;
1 red
2
3 blue
4
\.
copy people from stdin;
1 bob smith
2 tom jones
3 jane doe
4 mike porter
\.
select fname,lname,color,favorite_food from people,food,color where
people.id=food.id and people.id=color.id;


Udv: rpetike


---------------------------(end of broadcast)---- -----------------------
TIP 3: if posting/reading through Usenet, please send an appropriate
subscribe-nomail command to majordomo@postgresql.org so that your
message can get through to the mailing list cleanly

-- 
Brian Avis
SEARHC Medical Clinic
Juneau, AK 99801
(907) 463-4049
cd /pub
more beer

Re: Slightly OT: outer joins

From
"Russell Miller"
Date:
It would probably be better to set it up like this, if that's what you're
going to do:

id    person_id    food_id    color_id
1    1                 2              3

etc...

person
1 bob smith
etc...

this way if there are two people named bob smith you still can have a unique
person.  Otherwise your table design breaks down at that point.

This is also probably the most normalized way to do it...

Note also that using this method, if you need to change a name, food, or
color, the changes will happen instantly across the whole table structure.

--Russell

----- Original Message -----
From: "Brian Avis" <brian.avis@searhc.org>
To: "Risko Peter" <rpetike@freemail.hu>
Cc: "Fran Fabrizio" <ffabrizio@mmrd.com>; <pgsql-general@postgresql.org>
Sent: Tuesday, November 20, 2001 9:13 AM
Subject: Re: [GENERAL] Slightly OT: outer joins


> I'm sort of a beginner myself so forgive me if this is wrong. But that
> solution sort of assumes that data is being put into the tables at the
> same time.
>
> Wouldn't a better solution be to setup the first table like this.
>
> people
>
> ------------------------------
> |  id  |  fname  |  lname  |  food_id  |  color_id  |
> ------------------------------
> |  1   |  bob       |  smith    |       2        |       3           |
> ------------------------------
>
>
> Then you should be able to do a normal join type select and get the
> right results no matter what.
>
>
> Risko Peter wrote:
>
> >On Tue, 20 Nov 2001, Fran Fabrizio wrote:
> >
> >>This is a little off topic but this is the best source of SQL knowledge
> >>I know about so hopefully this will be interesting enough for someone to
> >>answer. :-)
> >>I've got the following tables:
> >>Table people
> >>id    fname    lname
> >>1     bob       smith
> >>2     tom       jones
> >>3     jane      doe
> >>4     mike     porter
> >>Table food
> >>id    favorite_food
> >>2     eggrolls
> >>3     ice cream
> >>Table color
> >>id     color
> >>1      red
> >>3      blue
> >>I want a query to produce the result set:
> >>fname   lname   favorite_color  favorite_food
> >>bob      smith     red               null
> >>tom      jones     null              eggrolls
> >>jane      doe       blue            ice cream
> >>mike    porter     null             null
> >>I'm having lots of trouble getting the right result or knowing whether
> >>this is even a valid usage of outer joins.  Can somebody show me a
> >>working query?  Thanks!
> >>
> >Hi Fran!
> >
> >  I'm a beginner, and maybe I will misinform you, but I think in the
above
> >case you want your tables being joined by the ID column. In that case you
> >_should_ have a row in your auxiliary tables (color, food) for every
> >occuring IDs in the main table. It will solve your problem:
> >---
> >drop table people;
> >drop table food;
> >drop table color;
> >create table people(id int4,fname char(10),lname char(10));
> >create table food(id int4,favorite_food char(10));
> >create table color(id int4,color char(10));
> >copy food from stdin;
> >1
> >2 eggrolls
> >3 ice cream
> >4
> >\.
> >copy color from stdin;
> >1 red
> >2
> >3 blue
> >4
> >\.
> >copy people from stdin;
> >1 bob smith
> >2 tom jones
> >3 jane doe
> >4 mike porter
> >\.
> >select fname,lname,color,favorite_food from people,food,color where
> >    people.id=food.id and people.id=color.id;
> >
> >
> >Udv: rpetike
> >
> >
> >---------------------------(end of broadcast)---------------------------
> >TIP 3: if posting/reading through Usenet, please send an appropriate
> >subscribe-nomail command to majordomo@postgresql.org so that your
> >message can get through to the mailing list cleanly
> >
>
> --
> Brian Avis
> SEARHC Medical Clinic
> Juneau, AK 99801
> (907) 463-4049
> cd /pub
> more beer
>
>
>


---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.298 / Virus Database: 161 - Release Date: 11/13/01


_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com


Re: Slightly OT: outer joins

From
Fran Fabrizio
Date:
Thanks everyone for the replies and instruction.

I agree that there are better ways to layout the tables, but I'm sort of the guy
who gets handed the crappy poker hand while it's owner goes to the restroom and
is expected to make it a winner. :-)  In other words, I really can't lay out the
tables the way I would've wanted to.

So, within those contraints Randal hit it right on the nose.  I was definitely
not catching on enough to see that the 'NATURAL' option to the joins is an
obvious choice, which was part/all of my problem.  Thanks Randal and everyone!

-Fran

"Randal L. Schwartz" wrote:

> Got it on the first try:
>
> test=# select * from people natural left join color natural left join food;
>  id | fname | lname  | color | favorite_food
> ----+-------+--------+-------+---------------
>   1 | bob   | smith  | red   |
>   2 | tom   | jones  |       | eggrolls
>   3 | jane  | doe    | blue  | ice cream
>   4 | mike  | porter |       |
> (4 rows)
>
> That's presuming "id" matches "id" in each table, thus the easy
> use of the "natural" keyword.  The "left join" is what gives you
> nulls on the right.


Re: Slightly OT: outer joins

From
merlyn@stonehenge.com (Randal L. Schwartz)
Date:
>>>>> "Fran" == Fran Fabrizio <ffabrizio@mmrd.com> writes:

Fran> So, within those contraints Randal hit it right on the nose.  I
Fran> was definitely not catching on enough to see that the 'NATURAL'
Fran> option to the joins is an obvious choice, which was part/all of
Fran> my problem.  Thanks Randal and everyone!

[..]

>> test=# select * from people natural left join color natural left join food;

Well, even without the natural part of the join, let's presume
that people.id needed to be matched to color.people_id,
you could say that as:

select id, fname, lname, color, favorite_food from
  people
  left join color on people.id = color.people_id
  left join food on people.id = food.people_id

So the main clue wasn't the NATURAL, it was the LEFT JOIN, to give you
the nulls for the table rows that didn't match.

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!