It depends on what you're modeling. Given your example above do you want to be able to find the team member best suited to a given problem?
If that is the case then I would recommend something like this:
Imagine roles and skills as vertices in an undirected graph. A given role is linked (via an edge) to each skill it is capable of (assuming skills are given by role and aren't just based on individual). Now connect all team members to whatever roles they have on the team and the team members to the appropriate teams.
This graph now models the associations between your teams, team members, their roles, and the skills they should have given their roles.
Now to map a given problem to a team member (or even team) take a problem and connect it to each of the different skills you think it'll need (ie. Email, DB, Web UI, Web Services, etc.). Now you can relate problems to these entities as well.
I won't go over every type of report you could run with this but here's a simple one. If you want to find a single person (if they exist) that can resolve that issue I would recommend a graph traversal like this:
class Problem
{
find_problem_solvers()
{
var problem_solvers = null
for each (skill in skills_required)
{
var possible_problem_solvers = skill.find_problem_solvers()
if(problem_solvers == null)
{
problem_solvers = new list().add_range(possible_problem_solvers)
}
else
{
for each problem_solver in problem_solvers:
{
if(problem_solver not in possible_problem_solvers)
problem_solvers.remove(problem_solver)
}
}
//No point continuing if we eliminated everyone!
if(problem_solvers is empty) break;
}
return problem_solvers
}
}
As you can see in this regard I don't have much of a use for the other posters' patterns. If you're trying to model domain security or a different business logic of some sort. Their techniques could very well be the right ones.
By the way it should be noted that the above algo is not optimal.