I've come here for help with a complicated query. I've tried a lot of different things for this and not quite got the results that I want. A watered down version of my schema is as follows: The three tables in question are an Employees Table, an EmployeeTraining Table, and a RequiredTraining table. The employees table holds information of an employee, such as empID,name, address, email, positionWorked, etc etc. The EmployeeTraining table holds an empID, and TrainingName.The RequiredTraining table has a Position and TrainingName.
Employees: empID , Name, Position
EmployeeTraining: empID , trainingName
requiredTraining: Position , trainingName
Here's some sample data, just to further clarify:
Employees
*EMPID~~Name~~Position~~
1 Ted Accountant
2 Bob Janitor
employeeTraining
**empID~~TrainingName**
1 Crunching Numbers
1 Microsoft Excel
1 Using an Abicus
2 Lemon Pledge 100
2 Scrubbing Toilets
requiredTraining
**position**~~**TrainingName**
Accountant Crunching Numbers
Accountant Microsoft Excel
Accountant Using an Abicus
Accountant TPS Reports
Janitor Lemon Pledge 100
Janitor Scrubbing Toilets
In english, and in the long run, I want to select an employee from a form and have a subform showing all of the training completed from that employee(SELECT * FROM Employees INNER JOIn EmployeeTraining on employees.empid = employeetraining.empID WHERE empID = me.empID)
I also want another subform that shows the training that an employee has NOT completed that is required for their current position. This is where I am struggling. I am not familiar or comfortable with using MS Access's query builder, but I have tried "find unmatched" queries as well as trying to write my own. This seems like a MINUS operation would work, but MS Access doesn't support MINUS. I have tried a LEFT JOIN with a null predicate as well as a NOT IN from the above query to a query of the requiredTraining table, but I haven't got the results I'm looking for.
For example, the result of the query I'm trying to write for this sample data would be:
for employeeID 1 (Ted the Accountant)
ted needs "TPS Reports" training
for employee 2 ( Bob the Janitor)
Bob has completed all of his training for his position.
An example of an attempted query I am trying is:
SELECT employees.position,employeeTraining.empid,employeetraining.TrainingName
FROM EmployeeTraining
InNER JOIN Employees ON EmployeeTraining.empid = employees.empid
WHERE empid = '1'
LEFT JOIN
SELECT TrainingName,Position FROM requiredTraining
ON EmployeeTraining.Training = RequiredTraining.Training
WHERE (((EmployeeTraining.Training is Null)))
Edit: This question has been answered. Thanks everyone for the help. Your queries, although each was different, all accomplished the goal.
The following query should return all employees with the training names that they need to complete:
select e.emp_id, rt.TrainingName
from employees e left outer join
RequiredTraining rt
on e.position = rt.position
where rt.TrainingName not in (select TrainingName from EmployeeTraining et where et.empId = e.EmpId)
The join in the "from" clause finds all the required trainings. The "where" clause then uses a correlated subquery to find the ones the employee has not completed.
you're very close actually, with your other query... you might try the NOT IN clause. For example, as you have said, you can get all the employees that have completed a particular training like so:
SELECT e.empID, e.name, e.Position, et.TrainingName
FROM Employees e
JOIN EmployeeTraining et ON e.empID = et.empID
WHERE empID = me.empID
What you want now, is all the employees that have NOT completed the training... you could just do a join on the trainingName table, making sure that the training type is not in the query you've already created, like so:
SELECT e.empID, e.name, e.Position, rt.TrainingName
FROM Employees e
JOIN requiredTraining rt ON e.Position = rt.Position
WHERE rt.TrainingName NOT IN
(
SELECT et.TrainingName
FROM Employees e
JOIN EmployeeTraining et ON e.empID = et.empID
WHERE empID = me.empID
)
AND e.empID = me.empID
Note that, as mentioned above, you don't actually need to join on the employees table... you could just use the following:
SELECT e.empID, e.name, e.Position, rt.TrainingName
FROM Employees e
JOIN requiredTraining rt ON e.Position = rt.Position
WHERE rt.TrainingName NOT IN
(
SELECT et.TrainingName
FROM EmployeeTraining
WHERE et.empID = me.empID
)
AND e.empID = me.empID
The query below is created from two MS Access queries with the SQL cut and pasted into derived tables. The two queries select the employee with their current training (#1) and the employee with their required training (#2). It is not updateable, but is easy to create. You can show only the missing training by adding a line at the end:
WHERE et.TrainingName Is Null
To select a single employee, you can add a line:
WHERE rt.EMPID=1 AND et.TrainingName Is Null
However, you mention a subform, so I expect you will wish to use link child and master fields to limit by employee.
SQL
SELECT rt.empid,
rt.position,
rt.trainingname,
et.trainingname AS IsTrained
FROM (SELECT employees.empid,
requiredtraining.position,
requiredtraining.trainingname
FROM employees
INNER JOIN requiredtraining
ON employees.position = requiredtraining.position) AS rt
LEFT JOIN (SELECT employees.empid,
employees.position,
employeetraining.trainingname
FROM employees
INNER JOIN employeetraining
ON employees.empid = employeetraining.empid) AS
et
ON ( rt.trainingname = et.trainingname )
AND ( rt.position = et.position )
AND ( rt.empid = et.empid );
The following query returns this result set based on your sample data as tested with Access 2007.
EMPID Position TrainingName
1 Accountant TPS Reports
SELECT
sub.EMPID,
sub.Position,
sub.TrainingName
FROM
(
SELECT
e.EMPID,
e.Position,
rt.TrainingName
FROM
Employees AS e
INNER JOIN RequiredTraining AS rt
ON e.Position = rt.position
) AS sub
LEFT JOIN EmployeeTraining AS et
ON
sub.TrainingName = et.TrainingName
AND sub.EMPID = et.empID
WHERE et.TrainingName Is Null;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.