【问题标题】:Advanced Query with a bit of logic带有一点逻辑的高级查询
【发布时间】:2012-01-05 15:16:29
【问题描述】:

我有一个高级查询/报告,我需要帮助在 Access 2007 中创建它。 我需要生成的查询是:

Employee Last, Employee First, Employee Role, Course Name, StartDate, EndDate, Attended

我需要处理的逻辑是:

  1. 如果用户参加了具有employeerole = courserole 的课程, 参加 = 是
  2. 如果用户没有参加 Employeerole = courserole 的课程, 参加 = 没有
  3. 如果用户没有参加并且没有匹配的课程 CourseRole,已参加 = 没有具有该角色的课程

添加一些额外的逻辑会很好:将培训师最后添加到选择
逻辑:如果 Data isNull,Trainer Last = No Trainer Assigned

它不会让我发布数据库的图片。所以这里是具有参照完整性的表:

Tables:  Fields
Employee: Employee_PK, Employee_Last, Employee_first, Employee_userid   
Role: Role_PK, RoleNAme  
EmployeeRole: EmployeeRole_PK, Employee_ID, Role_ID  
Location: Location_PK, Location  
Course: Course_PK, StartDate, EndDate, CourseName, CourseNotes, Location_ID  
CourseAttendance: CourseAttendance_PK, Course_ID, Employee_ID  
CourseRole: CourseRole_PK, Course_ID, Role_ID  
Trainer: Trainer_PK, TrainerLast, TrainerFirst  
TrainerCourse:Trainer_PK, Trainer_ID, Course_ID  

因此您可以看到它已标准化,并且需要多个多对多表
PK 代表主键,ID 用作外键。所以是的,这些都可以。

编辑:
此查询已发布在 cmets:
我已经尝试了许多查询。

SELECT qryEmployeeCoursesForRole.*, IIf(IsNull([courseattendance_PK]),"No","Yes") AS Attended 
FROM qryEmployeeCoursesForRole 
LEFT JOIN CourseAttendance 
    ON (qryEmployeeCoursesForRole.COURSE_ID = CourseAttendance.COURSE_ID) 
    AND (qryEmployeeCoursesForRole.EMPLOYEE_ID = CourseAttendance.EMPLOYEE_ID);  

这个不处理 No course defined 的异常——

Course Table:
COURSE_PK   START DATE  END DATE    COURSENAME    NOTES         LOCATION_ID  
1           12/2/2012   12/2/2012   OTC           No Notes            3  
2           12/1/2012   12/1/2012   OTC           No Note             2   
3           1/5/2012    1/5/2012    Requistions  Text Text Text       1 
                                      and P-Cards

CourseAttendance Table:
COURSEATTENDANCE_PK COURSE_ID   EMPLOYEE_ID  
1                   1               1  
2                   2               2  

CourseRole Table:
COURSEROLE_PK   COURSE_ID   ROLE_ID  
1                   1         1  
2                   1         2  
3                   1         3  
4                   2         1  
5                   2         2  

Employee Table:
EMPLOYEE_PK EMPLOYEE_LAST   EMPLOYEE_FIRST  EMPLOYEE_USERID  
1              Ables        Christopher        LG854  
2              Ables        Gary               LC876  
3              Ables        Steven             LQ875  

EmployeeRole Table:
EMPLOYEEROLE_PK EMPLOYEE_ID ROLE_ID  
1                     1         1  
2                     1         2  
3                     1         3  
4                     2         1  
5                     2         2  
6                     3         4  

Location Table:
LOCATION_PK LOCATION  
1             New York  
2             New Brunfels  
3             Ontario  
4             China  

Role Table:
ROLE_PK ROLENAME  
1             Service Coordinator    
2             Service Planner  
3             Service Entry  
4             AP Invoice  

Trainer Table:
TRAINER_PK  TRAINER_LAST    TRAINER_FIRST   TRAINER_USERID  
1              Brunet              Janell     
2              Gibson              Jim             hb476  
3              Taylor              Diana           hblo7hg  

TrainerCourse Table:
TRAINERCOURSE_PK    TRAINER_ID  COURSE_ID  
1                     1         1  
2                     1         2  
3                     2         2  

现在我已经详细介绍了逻辑,看来这需要的不仅仅是一个花哨的查询。如果您需要我更具体,我可以,但它需要我上传文件或其他内容。

我创建的所有查询和查询原因:

 EmployeeCourseOutsideofRole
 SELECT CourseAttendance.EMPLOYEE_ID, CourseAttendance.COURSE_ID, Course.COURSE_NAME  
 FROM Course INNER JOIN (CourseAttendance LEFT JOIN qryEmployeeCoursesForRole ON  
 (CourseAttendance.COURSE_ID = qryEmployeeCoursesForRole.COURSE_ID) AND  
 (CourseAttendance.EMPLOYEE_ID = qryEmployeeCoursesForRole.EMPLOYEE_ID)) ON Course.COURSE_PK =  
 CourseAttendance.COURSE_ID
 WHERE (((qryEmployeeCoursesForRole.EMPLOYEE_ID) Is Null) AND     
 ((qryEmployeeCoursesForRole.COURSE_ID)  
 Is Null)); 
 If Employee took a Course and the CourseRole not equal to EmployeeRole  

 EmployeeCoursesForRoleSub:
 SELECT [Employee_last] & " " & [employee_first] AS FullName, Role.ROLENAME,  
 EmployeeRole.EMPLOYEE_ID, EmployeeRole.ROLE_ID  
 FROM Role INNER JOIN (Employee INNER JOIN EmployeeRole ON Employee.EMPLOYEE_PK =  
 EmployeeRole.EMPLOYEE_ID) ON Role.ROLE_PK = EmployeeRole.ROLE_ID;
 This is a SubQuery only--for next  

 qryEmployeeCourseForRole:
 SELECT qryEmployeeCoursesForRoleSub.*, CourseRole.COURSE_ID  
 FROM qryEmployeeCoursesForRoleSub LEFT JOIN CourseRole ON qryEmployeeCoursesForRoleSub.ROLE_ID =  
 CourseRole.ROLE_ID;
 This shows courserole with matching employeerole--a subquery for next  

 EmployeeCourseForRoleWAttended:  
 SELECT qryEmployeeCoursesForRole.*, IIf(IsNull([courseattendance_PK]),"No","Yes") AS Attended  
 FROM qryEmployeeCoursesForRole LEFT JOIN CourseAttendance ON (qryEmployeeCoursesForRole.COURSE_ID =  
 CourseAttendance.COURSE_ID) AND (qryEmployeeCoursesForRole.EMPLOYEE_ID =  
 CourseAttendance.EMPLOYEE_ID);  

用于调试的附加示例数据

 Employee Table: 
 Employee_PK     Employee_Last     Employee_First  
 Autonumber       Daigle             Jake
 Autonumber       Ryder              Canen  

 Role Table:
 Role_PK    RoleName  
  5            Asset Shipper
  6            Material Controller  
  7            Material MAnager  

 EmployeeRole Table:  
 EmployeeRole_PK     Employee_ID         Role_ID  
 Autonum              Whatever Daigle is       5  
 Autonum              Whatever Daigle is       1  
 Autonum              Whatever Ryder is        5
 Autonum              Whatever Ryder is        6    

 Course Table:             
 Course_PK    Course_Name  Course_StartDate  Course_EndDate  
   4           OTC           12/8/2011        12/9/2011  

 CourseRole Table:  
 CourseRole_PK   Course_ID      Role _ID   
   6               4              1 
   7               4              7  

 CourseAttendance:
 CourseAttendance_PK      Course_ID      Employee_ID
  Autonum                  4              Whatever Daigle is
  Autonum                  4              Whatever Ryder is

好的,我发布了示例数据。如果用户参加了一门完成其角色之一的课程,并且 courserole = employeerole 则查询报告他们已完成所有角色,则会出现问题。

我需要一份报告:

员工姓氏、员工名字、角色 1、课程名称、开始日期、结束日期、出席 但是逻辑需要在那里,因为我在帖子开头列出了它。

【问题讨论】:

  • 您的表格中存在一些差异。首先,您在 EmployeeRole 中有一个名为 Role_ID 的字段,是您的 Role 表中的 Role_PK 吗?在您的 EmployeeRole 表中还有 Employee_ID 是 Employee_PK 还是 Employee_userid 在您的 Employee 表中?
  • 编辑您的问题并发布一些示例数据会有所帮助
  • 大多数情况下,当人们说样本数据时,他们指的是相关表格的一小部分剪切并粘贴到问题中。
  • @Piercy 是的,发布实际数据很有帮助
  • 在您发布的查询中,您有 IIf(IsNull([courseattendance_PK]),"No","Yes") 但在您的表中,您的 courseattendance_PK 为 1 或 2,如果它是主键is 不能为空。因此无法通过此判断是或否。

标签: ms-access logic ms-access-2007


【解决方案1】:

它有点乱,但这应该让你开始。根据您上面的表结构,您的设计有点偏离。您有包含不必要列的表格,但这不是您的问题。

这可以分为 3 个不同的查询,或者只使用 UNION,如下所示:

'this first query gets you the employees who have attended
SELECT E.EmployeeLast, E.EmployeeFirst, R.RoleName AS EmployeeRole
    , C.CourseName, C.StartDate, C.EndDate, "Yes" AS Attended
FROM (((Employee AS E 
INNER JOIN EmployeeRole AS ER 
    ON E.EmployeePK=ER.EmployeeId) 
INNER JOIN Role AS R 
    ON ER.RoleID=R.RolePK) 
LEFT JOIN CourseAttendance AS CA 
    ON E.EmployeePK=CA.EmployeeID) 
LEFT JOIN Course AS C 
    ON CA.CourseID=C.CoursePK
WHERE E.EmployeePK IN (SELECT CA.EmployeeID 
                        FROM ((CourseAttendance CA 
                        INNER JOIN EmployeeRole ER 
                            ON CA.EmployeeId = ER.EmployeeId) 
                        INNER JOIN CourseRole CR 
                            ON ER.RoleId = CR.RoleId 
                            AND CA.CourseID = CR.CourseID));

UNION

'this second query gets you the employees who have not attended
SELECT E.EmployeeLast, E.EmployeeFirst, R.RoleName AS EmployeeRole
    , C.CourseName, C.StartDate, C.EndDate, "No" AS Attended
FROM (((Employee AS E 
INNER JOIN EmployeeRole AS ER 
    ON E.EmployeePK=ER.EmployeeId) 
INNER JOIN Role AS R 
    ON ER.RoleID=R.RolePK) 
LEFT JOIN CourseAttendance AS CA 
    ON E.EmployeePK=CA.EmployeeID) 
LEFT JOIN Course AS C 
    ON CA.CourseID=C.CoursePK
WHERE E.EmployeePK NOT IN (SELECT CA.EmployeeID 
                        FROM ((CourseAttendance CA 
                        INNER JOIN EmployeeRole ER 
                            ON CA.EmployeeId = ER.EmployeeId) 
                        INNER JOIN CourseRole CR 
                            ON ER.RoleId = CR.RoleId 
                            AND CA.CourseID = CR.CourseID));

UNION

'this final query gets you the employees who have not attended and there is no course with their role
SELECT E.EmployeeLast, E.EmployeeFirst, R.RoleName AS EmployeeRole
    , C.CourseName, C.StartDate, C.EndDate, "No Course With Role" AS Attended
FROM (((Employee AS E 
INNER JOIN EmployeeRole AS ER 
    ON E.EmployeePK=ER.EmployeeId) 
INNER JOIN Role AS R 
    ON ER.RoleID=R.RolePK) 
LEFT JOIN CourseAttendance AS CA 
    ON E.EmployeePK=CA.EmployeeID) 
LEFT JOIN Course AS C 
    ON CA.CourseID=C.CoursePK
WHERE ER.RoleID NOT IN (SELECT RoleID 
                        FROM CourseRole)
    AND E.EmployeePK NOT IN  (SELECT CA.EmployeeID 
                                FROM ((CourseAttendance CA 
                                INNER JOIN EmployeeRole ER 
                                    ON CA.EmployeeId = ER.EmployeeId) 
                                INNER JOIN CourseRole CR 
                                    ON ER.RoleId = CR.RoleId 
                                    AND CA.CourseID = CR.CourseID));

【讨论】:

  • 我现在要试试这个。在我编辑脚本以适应我的数据库后会报告
  • BlueFeet...我印象深刻。在我必须创建以获取示例数据的测试数据库上,它可以按预期工作。我将把它移到我的暂存数据库中并尝试一下。我会回来报告的。我非常感谢您的努力。
  • 好的,我认为第一个查询可能有问题。当我将其转储到具有更真实数据的暂存数据库中时,我将结果过滤为仅 1 个角色(此角色未定义课程)。据报道,有些人已经参加了=是这个角色,而其他人则是“没有角色的课程”。有什么想法吗?
  • 没有看到所有的数据是很困难的。正如我所说,我给你的查询是一个起点。您可能需要根据需要对其进行微调。如果您提供更多示例数据,我可能会尝试调试,但根据您提供的数据,我能够得到您想要的结果。
  • 是的,你做到了。我要将更多数据转储到我的测试数据库中。可能有一些不好的值。完成后我会回来报告的。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-25
  • 1970-01-01
相关资源
最近更新 更多