Question

I'm trying to select all Projects which have Employees who are AtWork.

Projects:
ProjName    |    EmpOnProj
--------------------------
Alpha       |    1, 2, 3
Beta        |    1, 3

Employees:
EmpID       |   EmpName    |   AtWork
-------------------------------------
1           |   John       |   TRUE
2           |   Mark       |   FALSE
3           |   Mary       |   TRUE

I need to output all projects which could currently be worked on; ie, I need to show Beta because the employees working on Beta are at work.

Currently I cannot say "ALL EMPLOYEES MUST BE AT WORK" only the following:

SELECT ProjName FROM Projects INNER JOIN 
Employees ON EmpOnProj.Value = EmpID
WHERE AtWork = true
GROUP BY ProjName

which returns both, as it sees one correct employee and displays the project.

Was it helpful?

Solution

I think I solved this one. Basically I'm saying 'show all projects except those where somebody is NOT at work'

http://sqlfiddle.com/#!3/36c48/2

SELECT DISTINCT
  p_global.ProjName 

FROM
  Projects AS p_global

WHERE
  p_global.ProjName NOT IN
    (SELECT DISTINCT
      p1.ProjName

    FROM 
      Projects p1 INNER JOIN Employees AS e ON p1.EmpOnProj = e.EmpID 

    WHERE
      e.AtWork = 0)

There may be a simpler solution but this works (or it looks like it anyway) :)

Edit: Modified to remove GROUP BYs as suggested in comments.

OTHER TIPS

If can't really answer your question but this stuff can guide you through simplification and can help you solve you question. Currently your table is not in good format. Instead of having comma separated values, why not do it in rows instead? Like this,

Projects:
ProjName    |    EmpOnProj
--------------------------
Alpha       |    1
Alpha       |    2
Alpha       |    3
Beta        |    1
Beta        |    3

In this way you can easily join both tables. Example

SELECT  a.EmpID, a.EmpName, 
        iif (ISNULL(b.EmpOnProj), 'False', 'True') AtWork
FROM    Employees a
        LEFT JOIN Projects b
            ON a.EmpID = b.EmpOnProj
WHERE   b.ProjName = 'Beta'

Let's assume you move beyond the EmpOnProj column, which, as implemented in your example, violates first normal form, and replace it with an associative entity called ProjEmp, whose primary key is (ProjName, EmpID)

SELECT p.ProjName FROM Projects p
LEFT OUTER JOIN 
(SELECT eop.ProjName FROM ProjEmp eop
    INNER JOIN JOIN Employees e
    ON e.EmpId = eop.EmpId
    AND e.AtWork = FALSE
) AS empNotHere
ON empNotHere.ProjName = p.ProjName
WHERE empNotHere.ProjName IS NULL
;

I'm assuming I misunderstood your question since your SQL seems to contradict the schema you provided. But if your table is formatted the way you listed, you have to jump through hoops. Here's a solution that involves making a UDF, to avoid extremely complicated SQL.

Add this to a module:

Function WhoIsAtWork() As String
    Dim rs As Recordset
    Set rs = CurrentDb.OpenRecordset("Select * from Employees where AtWork = true Order by EmpID")
    Do While Not rs.EOF
        WhoIsAtWork = WhoIsAtWork & rs!EmpID & ", "
        rs.MoveNext
    Loop
    If Len(WhoIsAtWork) <> 0 Then
        WhoIsAtWork = Left(WhoIsAtWork, Len(WhoIsAtWork) - 2)
    End If
    rs.Close
    Set rs = Nothing
End Function

Then your SQL would be this:

SELECT ProjName
FROM Projects
WHERE Projects.EmpOnProj=WhoIsAtWork();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top