dbTalk Databases Forums  

Listing multiple joins on one row

comp.databases.postgresql comp.databases.postgresql


Discuss Listing multiple joins on one row in the comp.databases.postgresql forum.



Reply
 
Thread Tools Display Modes
  #1  
Old   
Ivan K.
 
Posts: n/a

Default Listing multiple joins on one row - 12-22-2009 , 12:55 PM






This is not a Postgres specific question.

Given two simple tables tracking the marriages between
people:


Quote:
create table person (
person_id serial not null, primary key (person_id),
name text not null
);

create table marriage (

marriage_id serial not null, primary key (marriage_id),
husband_id int not null, foreign key (husband_id) references person (person_id),
wife_id int not null, foreign key (wife_id) references person (person_id),
marriage_date timestamp null
);

The simple query:

Quote:
select distinct
person.person_id,
person.name,
marriage.marriage_id,
marriage.marriage_date
from
person
left join marriage on
(person.person_id = marriage.husband_id or person.person_id = marriage.wife_id)
order by
person.name,
marriage.marriage_date;

will produce multiple rows per person.name, if that particular
person has been married multiple times, such as:

Quote:
person_id name marriage_id marriage_date
34 fred 124 2002-01-23
212 sally 63 1995-06-01
212 sally 1221 2004-08-01
169 george 143 1988-02-22
WHAT I WOULD LIKE TO DO, is to collapse the rows
of multiple people into one row and have a query result
that looks like this:

Quote:
person_id name marriage_id_1 marriage_date_1 marriage_id_2 marriage_date_2
34 fred 124 2002-01-23
212 sally 63 1995-06-01 1221 2004-08-01
169 george 143 1988-02-22
no matter how many marriages any one person
may have had.


Can such a query be written entirely with SQL?
Or is there a common stored procedure that people
use?

Thanks!

Reply With Quote
  #2  
Old   
Mladen Gogala
 
Posts: n/a

Default Re: Listing multiple joins on one row - 12-22-2009 , 01:23 PM






On Tue, 22 Dec 2009 10:55:31 -0800, Ivan K. wrote:

Quote:
WHAT I WOULD LIKE TO DO, is to collapse the rows of multiple people into
one row and have a query result that looks like this:

person_id name marriage_id_1 marriage_date_1 marriage_id_2
marriage_date_2 34 fred 124 2002-01-23
212 sally 63 1995-06-01 1221 2004-08-01 169 george
143 1988-02-22

no matter how many marriages any one person may have had.


Can such a query be written entirely with SQL? Or is there a common
stored procedure that people use?

Thanks!
I had a similar question the other day and Laurenz suggested using the
unnest function.



--
http://mgogala.byethost5.com

Reply With Quote
  #3  
Old   
Ivan K.
 
Posts: n/a

Default Re: Listing multiple joins on one row - 12-22-2009 , 03:22 PM



I have an answer to my question. Evidently,
the "create aggregate" statement can help me.
First, I create this:


Quote:
CREATE AGGREGATE textcat_all(
basetype = text,
sfunc = textcat,
stype = text,
initcond = ''
);
And then, this query will do what I want:

Quote:
select
person.person_id,
person.name,
textcat_all( marriage.marriage_id || '; ') as marriage_ids,
textcat_all( marriage.marriagedate || '; ') as marriage_dates
from
person
left join marriageon
(person.person_id = marriage.husband_id or person.person_id = marriage.wife_id)
group by
person.person_id,
person.birthdate
order by
person.name;
The only problem remaining, is that
I would like the marriage dates to be in order.
The following query does that, but it is
_very_ slow. Does anybody have a suggestion?

Quote:
select
person.person_id,
person.name,
textcat_all( blah_blah.marriage_id || '; ') as marridage_ids,
textcat_all( blah_blah.marriagedate || '; ') as marriage_dates
from
person
left join
(
select
marriage.marriage_id,
marriage.marriage_date,
marriage.husband_id,
marriage.wife_id
from marriage
order by marriage.marriage_date
)
blah_blah on
(person.person_id = blah_blah.husband_id or person.person_id = blah_blah.wife_id)
group by
person.person_id,
person.birthdate
order by
person.name
;
Thanks!

Reply With Quote
  #4  
Old   
Ivan K.
 
Posts: n/a

Default Re: Listing multiple joins on one row - 12-22-2009 , 03:27 PM



CREATE AGGREGATE textcat_all(
basetype = text,
sfunc = textcat,
stype = text,
initcond = ''
);



And then, this query will do what I want:


select
person.person_id,
person.name,
textcat_all( marriage.marriage_id || '; ') as marriage_ids,
textcat_all( marriage.marriagedate || '; ') as marriage_dates
from
person
left join marriageon
(person.person_id = marriage.husband_id or person.person_id =
marriage.wife_id)
group by
person.person_id,
person.birthdate
order by
person.name;


The only problem remaining, is that
I would like the marriage dates to be in order.
The following query does that, but it is
_very_ slow. Does anybody have a suggestion?


select
person.person_id,
person.name,
textcat_all( blah_blah.marriage_id || '; ') as marridage_ids,
textcat_all( blah_blah.marriagedate || '; ') as marriage_dates
from
person
left join
(
select
marriage.marriage_id,
marriage.marriage_date,
marriage.husband_id,
marriage.wife_id
from marriage
order by marriage.marriage_date
)
blah_blah on
(person.person_id = blah_blah.husband_id or person.person_id =
blah_blah.wife_id)
group by
person.person_id,
person.birthdate
order by
person.name;



Thanks!

Reply With Quote
  #5  
Old   
Ivan K.
 
Posts: n/a

Default Re: Listing multiple joins on one row - 12-22-2009 , 06:42 PM



I have an answer to my question. Evidently,
the "create aggregate" statement can help me.
First, I create this:


CREATE AGGREGATE textcat_all(
basetype = text,
sfunc = textcat,
stype = text,
initcond = ''
);



And then, this query will do what I want:


select
person.person_id,
person.name,
textcat_all( marriage.marriage_id || '; ') as marriage_ids,
textcat_all( marriage.marriagedate || '; ') as marriage_dates
from
person
left join marriageon
(person.person_id = marriage.husband_id or person.person_id =
marriage.wife_id)
group by
person.person_id,
person.birthdate
order by
person.name;


The only problem remaining, is that
I would like the marriage dates to be in order.
The following query does that, but it is
_very_ slow. Does anybody have a suggestion?


select
person.person_id,
person.name,
textcat_all( blah_blah.marriage_id || '; ') as marridage_ids,
textcat_all( blah_blah.marriagedate || '; ') as marriage_dates
from
person
left join
(
select
marriage.marriage_id,
marriage.marriage_date,
marriage.husband_id,
marriage.wife_id
from marriage
order by marriage.marriage_date
)
blah_blah on
(person.person_id = blah_blah.husband_id or person.person_id =
blah_blah.wife_id)
group by
person.person_id,
person.birthdate
order by
person.name;



Thanks!

Reply With Quote
  #6  
Old   
Bob Badour
 
Posts: n/a

Default Re: Listing multiple joins on one row - 12-22-2009 , 07:02 PM



Ivan K. wrote:

Quote:
person
left join
(
select
marriage.marriage_id,
marriage.marriage_date,
marriage.husband_id,
marriage.wife_id
from marriage
order by marriage.marriage_date
)
blah_blah on
(person.person_id = blah_blah.husband_id or person.person_id =
blah_blah.wife_id)
This is just a guess so your mileage may vary. The order by marriage
date does not help the join on person id. I would try prefixing the
order with the person id, but the twist is you want to join on 2
different person ids. I suggest trying something along the lines of:

person
left join (
select
husband_id as person_id
, marriage_date
, marriage_id
from marriage
union
select
wife_id as person_id
, marriage_date
, marriage_id
from marriage
order by person_id, marriage_date
) holy_union
on person.person_id = holy_union.person_id

--
is there something in it for them, like maybe bailouts, if they can
panic us into doing something politically to cover them?

November 19, 2007 - John S Bolton

http://tinyurl.com/y9e4vxh

Reply With Quote
  #7  
Old   
Ivan K.
 
Posts: n/a

Default Re: Listing multiple joins on one row - 12-28-2009 , 02:40 PM



On Dec 22, 7:02*pm, Bob Badour <bbad... (AT) pei (DOT) sympatico.ca> wrote:
Quote:
person
left join (
* *select
* * * *husband_id as person_id
* * *, marriage_date
* * *, marriage_id
* *from marriage
* *union
* *select
* * * *wife_id as person_id
* * *, marriage_date
* * *, marriage_id
* *from marriage
* *order by person_id, marriage_date
) holy_union
on person.person_id = holy_union.person_id
That is an outstanding solution.
It sorts the marriages by date and is
_fast_. Your "holy_union" humor is
much appreciated too.

I need to learn more about the union
operator.

Thanks!

Reply With Quote
Reply




Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.3
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.