问题
I'm working on a training tracker program and I'm at a point where I can't figure out the SQL query.
I have 3 tables: employees, trainingRecords, masterList
.
employees
and trainingRecords
are related through the empID
fkey.
trainingRecords
and masterList
are related through the TID
fkey.
Right now the training records table is blank because nothing has been entered (all employees have no training).
I want to populate a listbox with all of the items in the masterList that are unaccounted for in the trainingRecords
table.
Since the trainingRecords
table is blank, it should be returning lName, fName
from the employees
table and docName, docNumber
for all entries in the master list.
I'm stumped. Any suggestions?
回答1:
I'm assuming you want to display all employees multiple times with the training documents they have not done yet.
SELECT a.lName, a.fName, b.docNumber, b.docName
FROM
(SELECT e.lName, e.fName, t.TID
FROM employees e
LEFT JOIN trainingRecords t ON e.empID = t.empID
) AS a,
(SELECT m.docNumber, m.docName, t.TID
FROM masterList m
LEFT JOIN trainingRecords t ON m.TID = t.TID
) AS b
WHERE a.TID IS NULL OR b.TID IS NULL
ORDER BY a.lName, b.docNumber
example results:
lName fName docNumber docName
Simpson Homer 1 Nuclear Physics for Dummies
Simpson Homer 2 Nuclear Physics for Beginners
Simpson Homer 3 Advanced Nuclear Physics
Simpson Lisa 3 Advanced Nuclear Physics
回答2:
You want LEFT JOIN, on the left side of the join will be the table that you know will contain everything and on the right will be what you are testing against.
select masterList.* from masterList LEFT JOIN trainingRecords ON(masterList.TID = trainingRecords.TID) WHERE trainingRecords.TID IS NULL;
回答3:
Okay, you have to JOIN all three tables with the trainingRecords table in the middle because it has the columns necessary to link the other two tables. Your query will look something like this:
SELECT E.lName, E.fName, ML.docName, ML.docNumber FROM
(employees E LEFT OUTER JOIN trainingRecords TR ON E.empID = TR.empID)
RIGHT OUTER JOIN masterList ML ON ML.TID = TR.TID
WHERE TR.TID IS NULL
What's happening here?
First, you're doing a LEFT OUTER JOIN of employees and trainingRecords. The LEFT OUTER is to ensure that all the records from employees show up even if there's no match in trainingRecords (which of course don't exist since trainingRecords has no data at all).
Then, you're taking the results of that query and RIGHT OUTER JOINing them to masterList. The RIGHT OUTER guarantees that all masterList records will be included even if there are no matches in trainingRecords.
Finally, WHERE TR.TID IS NULL filters out any records that actually matched any (future) records in trainingRecords.
回答4:
Why not use Full Join? What I use is:
Select A.* from A Full Join B on A.ID = B.ID where B.ID is NULL
来源:https://stackoverflow.com/questions/4048709/sql-query-list-all-items-in-one-table-that-do-not-appear-in-another-table