Here's one way. The expected indexes are essential.
DECLARE @Emp TABLE
(
Empid INT PRIMARY KEY CLUSTERED,
EmpName VARCHAR(10)
)
DECLARE @Proj TABLE
(
ProjID INT PRIMARY KEY CLUSTERED,
ProjName VARCHAR(10)
)
DECLARE @EmpProj TABLE
(
EmpID INT,
ProjID INT,
PRIMARY KEY CLUSTERED (EmpID, ProjID)
)
INSERT INTO @Emp SELECT 1, 'Tony' UNION ALL SELECT 2,'Romo'
INSERT INTO @Proj SELECT 1, 'Project 1' UNION ALL SELECT 2, 'Project 2'
INSERT INTO @EmpProj SELECT 1, 1 UNION ALL SELECT 2, 1 UNION ALL SELECT 2, 2
;
WITH
cte AS
( --=== Find employees NOT in a project
SELECT e.EmpID, p.ProjID FROM @Emp e CROSS JOIN @Proj p
EXCEPT
SELECT EmpID, ProjID FROM @EmpProj
) --=== Find employess NOT in the list above
SELECT *
FROM @Emp
WHERE EmpID NOT IN (SELECT EmpID FROM CTE)
;
--Jeff Moden
Change is inevitable... Change for the better is not.