У меня есть расширенный запрос / отчет, который мне нужно создать в Access 2007.
Сгенерированный мной запрос:
Employee Last, Employee First, Employee Role, Course Name, StartDate, EndDate, Attended
Логика, которая мне нужна, это:
- ЕСЛИ пользователь посещал курс с сотрудникомerole = courserole,
Присутствовал = да
- Если пользователь не посещал курс с Employeerole = courserole,
Присутствовал = нет
- Если пользователь не посещал и нет курса с соответствием
CourseRole, Attended = Нет курса с этой ролью
Некоторую дополнительную логику, которую было бы неплохо добавить: Trainer Last to the Select
Логика: если данные равны Null, последний тренер = нет назначенного тренера
Это не позволит мне опубликовать изображение базы данных. Итак, вот таблицы со ссылочной целостностью:
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 используется в качестве внешнего ключа. Так что да, это нормально.
EDIT:
Этот запрос был размещен в комментариях:
Я пробовал несколько запросов.
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);
Этот не обрабатывает исключение "Не определен курс" -
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 = employeeerole, тогда запрос сообщает, что он выполнил ВСЕ свои роли.
Что мне нужно в одном отчете:
Фамилия сотрудника, Имя сотрудника, Роль 1, CoureName, Дата начала, Дата окончания, Участник
Но логика должна быть там, как я перечислил выше в начале поста.