views:

132

answers:

2

i have the following tables:

Table: People (id, first, last, age, phone, etc . .)
Table: Roles (id, name)
Table: Skills (id, name)
Table: People_Roles (id, personID^, roleID^)
Table: People_Skills (id, personID^, skillID^)

^ = foreign key

I basically want a query that gives me the full result set of all people and their roles and there skills.

Person.First, Person.Last, Roles.Name, Skills.Name

+3  A: 
SELECT p.first, p.last, r.name, s.name
FROM People p
LEFT JOIN People_Roles pr
ON pr.personID = p.id
INNER JOIN Roles r
ON pr.roleID = r.id
LEFT JOIN People_Skills ps
ON ps.personID = p.id
INNER JOIN Skills s
ON ps.skillID = s.id

This query will select you all the people, even those without Roles or Skills assigned.

Li0liQ
but if i do all inner joins if there is a person with a skill and not a role then it wont show a records. I want to see all combinations. i thought this was an outer join ??
ooo
@oo I've written a comment about it :). Updated the answer for your pleasure.
Li0liQ
this still only gives me rows where there is a skill or a role . .what if there is a person with no skill or row . . how will that show up ?
ooo
@oo that person will show up as a person with NULL in both Skill and Role names. As soon as we use LEFT JOIN it returns ALL the records from the left table that means People table.
Li0liQ
A: 

This query will work:

SELECT Person.First, Person.Last, Roles.Name, Skills.Name  
FROM People 
 LEFT JOIN People_Skills 
  ON People.id = People_Skills.personID
 INNER JOIN Skills
  ON People_Skills.skillID = Skills.id
 LEFT JOIN People_Roles 
  ON People.id = People_Roles.personID
 INNER JOIN Roles
  ON People_Roles.roleID = Skills.id

By the way, why your "bridge" tables have their own ID. I would just use a compound key made of PersonID and the corresponding foreign key (skillsID or rolesID) to ensure that every pair can only be made once.

Oded
but if i do all inner joins if there is a person with a skill and not a role then it wont show a records. I want to see all combinations. i thought this was an outer join ??
ooo
Indeed, but then you may have rows with many nulls in them
Oded
agreed but i guess i would need to deal with that in code . . or go back to my original method of having a seperate query for each bridge table per record in the people table . .
ooo
Do a where clause and compare "is Null" to remove the null rows you don't want.
Vaccano
And left joins would probably be better than full joins
Vaccano
Updated query to return full result set, as described.
Oded
i am trying to figure out if its worth it as i have about 10 different bridge tables . . coding it in a loop is definatley much simpler but not sure on performance . .
ooo
Performance wise, calling the DB 10 times will cost a lot more than calling it once and getting a larger result set, unless the result set is massive...
Oded
and there is also the complexity of parsing the results and renormalizing it in my object model as my object model is a Person object with an array of Skills and an array of Roles
ooo
There is always a tradeoff... you need to decide how much of one you are willing to accept.
Oded