MCS
MCS

Reputation: 22541

SQL Server query: how to return set of values based on condition?

Consider the following scenario (a bit contrived, but less complex than the real scenario I'm struggling with):

A university with an online document management system wants to limit which professors can see which documents. Some professors can see documents belonging to any department but some can only see documents belonging to specific departments.

Here's the schema:

create table Professors (
    ProfessorId int primary key,
    ProfessorName varchar(50)
);

create table Departments (
    DepartmentId int primary key,
    DepartmentName varchar(50)
);

create table ProfessorDepartments (
    ProfessorId int,
    DepartmentId int
);

insert into Professors values (1, 'Professor A'), (2, 'Professor B');
insert into Departments values (1, 'Chemistry'), (2, 'Computer Science'), (3, 'Math'), (4, 'Physics');
insert into ProfessorDepartments values (1,2), (1,3);

And here's the tricky part: a professor with unrestricted access will not have any departments listed in the ProfessorDepartments table. (That way, said professor will automatically be given access to any new departments.)

How can I get the list of allowed departments for a specific professor? The list needs to come from the ProfessorDepartments table if the professor has limited access and from the Departments table if the professor has unrestricted access.

Upvotes: 2

Views: 704

Answers (5)

Mark Kram
Mark Kram

Reputation: 5832

I might not be fully understanding your question, but how about this:

SELECT P.ProfessorName
        ,CASE WHEN D.DepartmentName IS NULL THEN 'Unrestricted Access' ELSE D.DepartmentName END
FROM Professors P LEFT OUTER JOIN ProfessorDepartments PD ON
    P.ProfessorId = PD.ProfessorId
    LEFT OUTER JOIN Departments D ON
        PD.DepartmentId = D.DepartmentId

EDIT

After seeing Will's solution, I have updates my script:

SELECT P.ProfessorName, D.DepartmentName
FROM Professors P 
        LEFT OUTER JOIN ProfessorDepartments PD ON P.ProfessorId = PD.ProfessorId
        LEFT OUTER JOIN Departments D ON PD.DepartmentId IS NULL OR PD.DepartmentId = D.DepartmentId

Upvotes: 0

Gabe
Gabe

Reputation: 6045

Dems answer look like the best one.

Here is my attempt.

SELECT 
    p.ProfessorName, d.DepartmentName
FROM #Professors p
CROSS JOIN #departments d
WHERE NOT EXISTS (
    SELECT * FROM #ProfessorDepartments pd WHERE pd.ProfessorId = p.ProfessorId)

UNION ALL

SELECT p.ProfessorName, d.DepartmentName
FROM #Professors p
INNER JOIN #ProfessorDepartments pd
ON pd.ProfessorId = p.ProfessorId
INNER JOIN #Departments d
ON d.DepartmentId = pd.DepartmentId

Upvotes: 1

Will P.
Will P.

Reputation: 8787

SELECT Professors.ID as ProfessorID, Departments.ID as DepartmentID, 
    Professors.ProfessorName, Departments.DepartmentName
FROM Professors
    LEFT OUTER JOIN ProfessorDepartments ON ProfessorDepartments.ProfessorID=Professors.ID
    LEFT OUTER JOIN Departments ON ProfessorDepartments.DepartmentID IS NULL OR 
        ProfessorDepartments.DepartmentID=Departments.ID

should do the trick

Upvotes: 2

MatBailie
MatBailie

Reputation: 86706

SELECT
  Professors.ProfessorName,
  Departments.DepartmentName
FROM
  Professors
LEFT JOIN
  ProfessorDepartments
    ON Professors.ProfessorId = ProfessorDepartments.ProfessorId
LEFT JOIN
  Departments
    ON ProfessorDepartments.DepartmentId = Departments.DepartmentId
    OR ProfessorDepartments.DepartmentId  IS NULL

Upvotes: 3

aF.
aF.

Reputation: 66687

You can do it like this:

declare @prof varchar(50)
select @prof = 'Professor B'

if(select count(pd.ProfessorId) from Professors p
    inner join ProfessorDepartments pd on p.ProfessorId = pd.ProfessorId
    where p.ProfessorName = @prof) = 0
begin
  select DepartmentName from Departments
end
else
begin
  select d.DepartmentName from Professors p
    inner join ProfessorDepartments pd on p.ProfessorId = pd.ProfessorId
    inner join Departments d on pd.DepartmentId = d.DepartmentId
    where p.ProfessorName = @prof
end

Upvotes: 0

Related Questions