这个问题自我最初发布以来已经更新,多亏了最初的受访者的帮助,我已经取得了一些进展,但仍然没有完全存在,并且无法弄清楚以下内容。
我有一份被分配角色的员工名单。每卷需要完成一组不同的培训。会话以一个表格记录,该表格输入到名为“TrainingSessions”的表格中。我想从“员工”表中获取一个名单列表,并将其与“TrainingSessions”的出席情况进行比较,并输出未参加所需培训课程的人员列表。
我已成功创建了一个查询,该查询提取员工姓名(和相关ID),并将其列为所分配角色所需的培训。
SELECT Employees.ID, Employees.LastName, Employees.FirstName, Trainings.ID, Trainings.TrainingTitle
FROM (EmployeeRoles INNER JOIN Employees ON EmployeeRoles.ID = Employees.Role) INNER JOIN Trainings ON EmployeeRoles.ID = Trainings.RequiredFor.Value
GROUP BY Employees.ID, Employees.LastName, Employees.FirstName, Trainings.ID, Trainings.TrainingTitle, Employees.Resignation
HAVING (((Employees.Resignation) Is Null));
我还创建了一个查询,以平衡TrainingSessions,以便每个与会者都在他们自己的行中列出。
SELECT TrainingSessions.TrainingTitle AS Title, TrainingSessions.SessionDate AS [Date], TrainingSessions.Attendance.Value AS Who, DateAdd("yyyy",[Trainings]![YearsValid],[SessionDate]) AS Due
FROM Trainings INNER JOIN TrainingSessions ON Trainings.ID = TrainingSessions.TrainingTitle
ORDER BY TrainingSessions.SessionDate;
我现在需要的是弄清楚如何将所需的培训与已完成的培训进行比较,并吐出未完成特定培训的员工名单。到目前为止,我能够获得的最接近的列表是每位员工从未参加过会议所需的培训,而不是特定工作人员未参加的培训。
以下是我的数据库现在的一些图片:
答案 0 :(得分:1)
我认为你遇到的问题不仅仅是这个问题。首先,TrainingSessions中的员工姓名似乎不一致 - 有些只有姓氏,有些有姓氏和姓氏。名字。目前尚不清楚它们是否与Employee表匹配。其次,Trainings中的RequiredFor字段看起来像在某些情况下列出了多个值 - 因此与Employees的匹配并不清楚。我假设它应该与Role字段匹配,并且Role将始终匹配Trainings表中的拼写等 - 但它仍然是从列表中提取它们的额外步骤。第三,你在训练中有一个YearsValid字段,所以假设你不仅需要检查出勤率,还要检查日期 - 也不是你的问题。第四,你在TrainingSessions中有说“不是一门课程” - 他们是否需要被排除在外?
所以要开始,我认为你需要考虑构建三个查询。
首先是必修课程清单。您需要最终得到一个类似于员工的表(最好带有ID,而不仅仅是名称)和必需的课程(再次,带有课程ID),可能还有YearsValid信息。每个员工每个要求可能需要1条记录 - 而不是一条记录中的多个要求。只要员工中的角色与培训中的角色匹配,就不难从您拥有的数据中汇总。将此保存为TrainingRequired。
SELECT Employees.ID AS EmployeeID, Employees.FirstName, Employees.LastName, Employees.Role, Trainings.ID AS TrainingID, Trainings.TrainingTitle, Trainings.YearsValid
FROM Employees, Trainings
WHERE (((InStr([RequiredFor],[Role]))>0));
然后,您需要对已完成的课程进行另一次查询。假设员工姓氏是唯一的,并且TrainingSessions表至少包含正确的姓氏,那么这样的事情就可以了。请注意,在大多数情况下,这是一个非常糟糕的假设,因此您可能需要一种不同的方式将员工ID放入此查询中。我也没有对Notes列中的信息进行任何调整。将此保存为TrainingCompleted。
SELECT Employees.ID AS EmployeeID, Employees.FirstName, Employees.LastName, Employees.Role, TrainingSessions.TrainingTitle AS TrainingID, TrainingSessions.SessionDate, TrainingSessions.Attendance
FROM Employees, TrainingSessions
WHERE (((InStr([Attendance],[LastName]))>0));
一旦这两个查询都正常工作并且同时具有EmployeeID和TrainingID,您可以将它们组合在一起以获得所需内容。
SELECT TrainingRequired.EmployeeID, TrainingRequired.FirstName, TrainingRequired.LastName, TrainingRequired.Role, TrainingRequired.TrainingID, TrainingRequired.TrainingTitle, TrainingCompleted.SessionDate, IIf((Now()-[SessionDate])/365<=[YearsValid],"X") AS [Current]
FROM TrainingRequired LEFT JOIN TrainingCompleted ON (TrainingRequired.TrainingID = TrainingCompleted.TrainingID) AND (TrainingRequired.EmployeeID = TrainingCompleted.EmployeeID);
此最终查询检查每个要求以查看课程是否已被采用且仍在YearsValid标准内。如果是这样,最后一列是“X”。如果不是,则最后一列为空白。如果需要,您可以进一步过滤以查看缺少的要求。
答案 1 :(得分:0)
我做到了!!!
首先:我创建了一个查询,输出一个平面表,将每个员工所需的所有培训放在一个单独的行上:
SELECT TrainingRequiredByName.Employees.ID AS EmpID, TrainingRequiredByName.Trainings.ID AS TrainID, TrainingRequiredByName.Employees.LastName AS [Last], TrainingRequiredByName.Employees.FirstName AS [First], TrainingRequiredByName.Trainings.TrainingTitle AS Title
FROM TrainingRequiredByName;
然后我创建了一个查询,输出一个平面表,将所有已完成的培训放在一个单独的行上:
SELECT Employees.ID AS EmpID, Trainings.ID AS TrainID, Employees.LastName AS [Last], Employees.FirstName AS [First], Trainings.TrainingTitle AS Title
FROM Trainings INNER JOIN (Employees INNER JOIN TrainingSessions ON Employees.ID = TrainingSessions.Attendance.Value) ON Trainings.ID = TrainingSessions.TrainingTitle;
然后我找到了一个不匹配的查询,比较每个查询的EmpID和TrainID,并输出我一直在搜索的列表!
感谢Don George帮助我朝着正确的方向前进。我不能告诉你我是多么兴奋得到一个我可以实际使用的结果!