Reputation: 726
I have a webapp for a school that pulls the locations of both students and faculty when they register for the system. These locations change over time, though (students change dorm, staff switch buildings), so I'm building a script to update them occasionally. I need to run a query that pulls in a list of userids and building names, and I'd like to do it in a single query for personal edification/masochistic reasons.
I have access to a central database that has the following (simplified) schema:
facstaff(userid, bldgcode)
students(userid, dorm)
buildings(bldgcode, building) # building is the human readable building name
and the query that I'm working with so far looks like this:
SELECT users.userid, buildings.building
FROM (SELECT userid, bldgcode FROM facstaff
UNION
SELECT userid, dorm AS bldgcode FROM students)
AS users
INNER JOIN buildings ON users.bldgcode=buildings.bldgcode
WHERE userid in (<list of users>);
The issue I'm having is that many students go on to work in the school after they graduate (student entries are not removed from the db on graduation), or will work and study simultaneously, so there are duplicate userid
after my union, but they have different bldgcode
so a simple distinct doesn't work. Basically I get results like this:
+----------+-----------------------+
| userid | building |
+----------+-----------------------+
| jimbo | Science Sphere |
| billiam | Dorm E11 |
| dwayne | Humanities Hall |
| mandar | Science Sphere |
| foobaz | Administration |
| fredrick | Physical Plant |
| fredrick | Dorm A6 |
+----------+-----------------------+
Fredrick is both a student and a staff member, so two locations come up with his name; one from facstaff
and one from students
. Ideally, there would be a way to enforce distinction in the userid
column so that the building coming from facstaff
would override anything coming out of students
. I'm open to other solutions though, of course. I appreciate any help!
Upvotes: 1
Views: 68
Reputation: 37398
To rephrase what you're looking for, if a user is both faculty and a student, that you want the faculty information to take precedence over the student information.
To do this, you can add a check to the students
part of your UNION
to only return a student if they aren't also a faculty member - implemented here with LEFT JOIN / IS NULL
:
SELECT users.userid, buildings.building
FROM (
SELECT userid, bldgcode FROM facstaff
UNION
SELECT userid, dorm AS bldgcode FROM students
LEFT JOIN facstaff ON facstaff.userid = students.userid
WHERE facstaff.userid IS NULL
) AS users
INNER JOIN buildings ON users.bldgcode=buildings.bldgcode
WHERE userid in (<list of users>);
Upvotes: 4