views:

702

answers:

6

I have some tables that benefit from many-to-many tables. For example the team table.

Team member can hold more than one 'position' in the team, all the positions are listed in the position db table. The previous positions held are also stored for this I have a separate table, so I have

  • member table (containing team details)
  • positions table (containing positions)
  • member_to_positions table (id of member and id of position)
  • member_to_previous_positions (id of member and id of position)

Simple, however the crux comes now that a team member can belong to many teams aghhh. I already have a team_to_member look-up table. Now the problem comes how do I tie a position to a team? A member may have been team leader on one team, and is currently team radio man and press officer on a different team. How do I just pull the info per member to show his current position, but also his past history including past teams. Do I need to add a position_to team table and somehow cross reference that, or can I add the team to the member to positions table?

It's all very confusing, this normalization.

A: 

Sounds like you need a many-to-many positions to teams table now.

duffymo
it looks like im going to end up with as many many-to-many tables as I am data storage tables, is that normal!!
Paul M
it is if the application requires many to many relationships....:)
Stuart
he he, yeah I suppose it does I have just never worked with anything like it. Essentially members can be in any team, work any position, the teams do events, which have locations, all of which change and cross reference each other, plus keep history! many to many means I can separate them all up if I need too making simple queries easy!thnkx
Paul M
A: 

Your team_to_member table can indeed have an extra column position_id to describe (or in this case point to) the position the member has within that team.

MSpreij
But if the player can have many positions, this fails...
Matchu
Not if those positions are for different teams. Can a player have different positions in the same team? Then it gets more complicated..
MSpreij
Yes think of a team as a yacht crew! A member can be a skipper on team A, and also the press man on Team A. But when he is bored he is also just a winchman on Team B for something to do! If I look up team B i want to see all members name, their position on team B and maybe the members 'other' teams and positions too! Confusing I know!
Paul M
+2  A: 

My first thought:

Give your many-to-many teams/members table an ID column. Every team-to-member relationship now has an ID.

Then create a many-to-many linking positions to team-member relationships.

This way, teams can have multiple members, members can have multiple teams, and members can have multiple positions on a per-team basis.

Now everything is nice and DRY, and all the linking up seems to work. Does that sound right to anyone else?

Matchu
Sounds right to me. Never seen a many-to-many link table link a regular table to another many-to-many link table (phew), neat trick.
MSpreij
Matchu, with the team-to-member many to many table, if I add an id, do I make this an index and keep the team_id and member_id as joint primary Key? Or not have it as an index?
Paul M
Also where do I add the date joined, date finished to the team or position table. aghh its complicated.
Paul M
Do dates during which a member holds a position matter? Or just when they were on the team?
Matchu
+3  A: 

It's perfectly legitimate to have a TeamPositionMember table, with the columns

Team_Id
Position_Code
Member_Id
Start_Date
End_Date NULLABLE

And and a surrogate ID column for Primary Key if you want; otherwise it's a 3-field composite Primary Key. (You'll want a uniqueness constraint on this anyway.)

With this arrangement, you can have a team with any set of positions. A team can have zero or more persons per position. A person can fill zero or more positions for zero or more teams.

EDIT:

If you want dates, just revise as shown above, and add Start_Date to the PK to allow the same person to hold the same position at different times.

le dorfier
ahh right so I can assign a primary key to more than 2 columns, thats interesting. (im using mysql workbench to build this). So you tick PK per field.
Paul M
There's a lot of repetition in this model, though...
Matchu
Repetition? This should be the minimum, with duplicates prevented.
le dorfier
I Like this, its clean. And can cope with a variety of situations. Its also similar to Walter mitty idea, same principle.
Paul M
The only thing that bugs me with this method is that it gets trickier to get a listing of just a player's team history, and what players are on any given team - either more server-side work, or tricker queries. But if you can find a clean way to do all that, it should be fine :)
Matchu
A: 

Get rid of member_to_previous_position table. Just use member_to_positions and have these columns:

MemberToPositionID (autoincrement OK only)
MemberID
PositionID
StartDate
EndDate

Then to find current positions, you do:

select * 
from member_to_positions 
where EndDate is null
RedFilter
What about linking to teams?
Matchu
+2  A: 

Yes, a many-to-many junction table can have additional attributes (columns).

For example, if there's a table called PassengerFlight table that's keyed by PassengerID and FlightID, there could be a third column showing the status of the given passenger on the given flight. Two different statuses might be "confirmed" and "wait listed", each of them coded somehow.

In addition, there can be ternary relationships, relationships that involve three entities and not just two. These tables are going to have three foreign keys that taken together are the primary key for the relationship table.

Walter Mitty
Walter really like this idea, it helped me to understand the whole concept better, I picked le dorfier as right answer as his example helped me out with the date, and he posted first :) wish I could award second place though!
Paul M