[Dbix-class] Three table relationships?

James Marca jmarca at translab.its.uci.edu
Mon Feb 5 22:53:08 GMT 2007


At approximately Fri, Feb 02, 2007 at 12:20:49PM +0000, Zbigniew Lukasiak wrote:
> On 1/31/07, Matt S Trout <dbix-class at trout.me.uk> wrote:
...
> 
> So here is an example for the general case, perhaps you could call it
...
> 
> select * from a, b, c where
> a.key1 = b.key2 and b.key1 = c.key2 and c.key1 = a.key2
> 
> With composed (key1, key2) primary keys for a, b and c tables.
> 
> This join is a three table relationship (just like the many to many
> case) - and I think it is not reducible to a superposition of two
> table relstionships (differently from the many to many case).

Sorry to pop in the middle here, but my understanding is that the
above relationship *is* reducible.  

The issues are covered in better detail in the O'Reilly book, Java
Database Best Practices, page 44 to 46.  

I wrote your relationships down, and they seem to translate to:
A= ActorRole
B= ActorFilm
C= FilmRole

so your condition:
> a.key1 = b.key2 and b.key1 = c.key2 and c.key1 = a.key2

is 

ActorRole         ActorFilm         FilmRole
 actorId (a.k1)    filmId  (b.k1)    roleId  (c.k1)
 roleId  (a.k2)    actorId (b.k2)    filmId  (c.k2)   

This is used by the book as an example of a database that isn't in
fifth normal form.  You can enter data that make sense in the db but
that produce nonsensical results (actors in roles in the wrong film).

In essense, you never guarantee that person A was in film B playing
Role C, all at the same time.  Instead, the table structure just hopes
that something else prevents generic roles such as "the President" or
"reporter" from being assigned the same roleId.  Otherwise, you may get a
case where some actor plays a reporter in one film, the president in
another, and if both those roles are in both films, you'll get the
actor playing the wrong role in the wrong film. For example (the
book's example seems to be in error, by the way):

actor        filmId      role             True or False?
1- J.Doe      101    1001- the President    true 
1- J.Doe      102    1002- a reporter       true
3- S.Queue    101    1002- a reporter       true 
4- A.Smithee  102    1001- the President    true
--------------------------------------------------
1- J.Doe      101    1002- a reporter       false
1- J.Doe      102    1001- the President    false


The solution is to create a trinary join table: 

Appearance
 actorId
 filmId
 roleId

And once again, the many to many relationship is intermediated by a
single (but this time trinary) table.

James



More information about the Dbix-class mailing list