以下のクエリは、私が理解しているとおり、探している情報を返します。キー句は、T-SQL で EXCEPT ステートメントを使用しています。EXCEPT は、2 番目のクエリに含まれていない最初のクエリのすべての行を返します。これを使用して、すべての必須コースまたはすべてのオプション コースを完了していない従業員を特定できます。わかりやすくするために一般的なテーブル式を使用しましたが、CTE をサブクエリとして使用することもできます。
;with EmployeesWithRequiredCourses as
(
select *
from Employee
where not exists
(
select CourseID
from Courses
inner join GroupTable on GroupTable.GroupID = Courses.GroupID
where GroupTable.GroupName = 'Required'
except
select Employee_Course.CourseID
from Employee_Course
inner join Courses on Courses.CourseID = Employee_Course.CourseID
inner join GroupTable on GroupTable.GroupID = Courses.GroupID
where Employee_Course.EmployeeID = Employee.EmployeeID
and GroupTable.GroupName = 'Required'
)
),
EmployeesWithOptionalCourses as
(
select *
from Employee
where not exists
(
select CourseID
from Courses
inner join GroupTable on GroupTable.GroupID = Courses.GroupID
where GroupTable.GroupName = 'Optional'
except
select Employee_Course.CourseID
from Employee_Course
inner join Courses on Courses.CourseID = Employee_Course.CourseID
inner join GroupTable on GroupTable.GroupID = Courses.GroupID
where Employee_Course.EmployeeID = Employee.EmployeeID
and GroupTable.GroupName = 'Optional'
)
)
select Employee.Department,
COUNT(EmployeesWithRequiredCourses.EmployeeID) as RequiredCourseCount,
COUNT(EmployeesWithOptionalCourses.EmployeeID) as OptionalCourseCount,
COUNT(Employee.EmployeeID) as EmployeeCount,
CAST(COUNT(EmployeesWithRequiredCourses.EmployeeID) as real)/CAST(COUNT(Employee.EmployeeID) as real) as RequiredCoursePercentage,
CAST(COUNT(EmployeesWithOptionalCourses.EmployeeID) as real)/CAST(COUNT(Employee.EmployeeID) as real) as OptionalCoursePercentage
from Employee
left outer join EmployeesWithRequiredCourses on EmployeesWithRequiredCourses.EmployeeID = Employee.EmployeeID
left outer join EmployeesWithOptionalCourses on EmployeesWithOptionalCourses.EmployeeID = Employee.EmployeeID
group by Employee.Department
ただし、以下のコメントに基づいて、各部門とコース名、そのコースを修了した従業員の数、部門内の全従業員、および部門内の修了した従業員の割合をリストする新しいクエリを作成しましたコース。前と同じように、共通のテーブル式を使用していますが、代わりにサブクエリを使用するように簡単に変換できます。
;with Departments as
(
select Department, COUNT(*) as DepartmentEmployeeCount
from Employee
group by Department
),
DepartmentCourse as
(
select Department, CourseName, DepartmentEmployeeCount
from Departments
cross join Courses
),
CompletedCourses as
(
select Department, CourseName, COUNT(*) as CourseCompletedCount
from Employee
inner join Employee_Course on Employee_Course.EmployeeID = Employee.EmployeeID
inner join Courses on Courses.CourseID = Employee_Course.CourseID
group by Department, CourseName
)
select DepartmentCourse.Department,
DepartmentCourse.CourseName,
CourseCompletedCount,
DepartmentEmployeeCount,
CAST(ISNULL(CourseCompletedCount,0) as real)/CAST(DepartmentEmployeeCount as real) as CourseCompletionPercentage
from DepartmentCourse
left outer join CompletedCourses on CompletedCourses.Department = DepartmentCourse.Department and CompletedCourses.CourseName = DepartmentCourse.CourseName
また、いくつかのテスト データを設定するために使用した SQL も含めているので、自分のデータベースとは一致しない可能性のある仮定を確認できます。
create table GroupTable
(
GroupID int not null,
GroupName varchar(50)
)
create table Courses
(
CourseID int not null,
GroupID int,
CourseName varchar(50)
)
create table Employee
(
EmployeeID int not null,
Name varchar(50),
SSN varchar(11),
Department varchar(50)
)
create table Employee_Course
(
EmployeeID int not null,
CourseID int not null
)
insert into GroupTable values (1, 'Required')
insert into GroupTable values (2, 'Optional')
insert into Courses values (1, 1, 'Course1')
insert into Courses values (2, 1, 'Course2')
insert into Courses values (3, 1, 'Course3')
insert into Courses values (4, 2, 'Course4')
insert into Courses values (5, 2, 'Course5')
insert into Courses values (6, 2, 'Course6')
insert into Employee values (1, 'Bob','122-45-1111', 'A')
insert into Employee values (2, 'Peter','124-45-2222', 'A')
insert into Employee values (3, 'Joe','125-45-3333', 'A')
insert into Employee values (4, 'Jimmy','126-45-4444', 'A')
insert into Employee values (5, 'Mary','127-45-5555', 'A')
insert into Employee values (6, 'Alice','122-45-6666', 'B')
insert into Employee values (7, 'Jennifer','124-45-7777', 'B')
insert into Employee values (8, 'Carter','125-45-8888', 'B')
insert into Employee values (9, 'Mason','126-45-9999', 'C')
insert into Employee values (10, 'Irina','127-45-0000', 'C')
insert into Employee_Course values (1,1)
insert into Employee_Course values (1,2)
insert into Employee_Course values (1,3)
insert into Employee_Course values (1,4)
insert into Employee_Course values (1,5)
insert into Employee_Course values (1,6)
insert into Employee_Course values (2,1)
insert into Employee_Course values (2,2)
insert into Employee_Course values (2,4)
insert into Employee_Course values (2,5)
insert into Employee_Course values (3,1)
insert into Employee_Course values (3,4)
insert into Employee_Course values (4,1)
insert into Employee_Course values (4,2)
insert into Employee_Course values (4,3)
insert into Employee_Course values (5,4)
insert into Employee_Course values (5,5)
insert into Employee_Course values (5,6)
insert into Employee_Course values (6,1)
insert into Employee_Course values (6,2)
insert into Employee_Course values (6,3)
insert into Employee_Course values (6,4)
insert into Employee_Course values (6,5)
insert into Employee_Course values (7,4)
insert into Employee_Course values (8,1)
insert into Employee_Course values (9,2)
insert into Employee_Course values (9,3)
insert into Employee_Course values (9,4)
insert into Employee_Course values (9,5)
insert into Employee_Course values (9,6)
insert into Employee_Course values (10,1)
insert into Employee_Course values (10,2)
insert into Employee_Course values (10,3)
insert into Employee_Course values (10,4)
insert into Employee_Course values (10,5)
insert into Employee_Course values (10,6)