• 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


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)