Bạn có thể làm như vậy, truy vấn này trước tiên sẽ điền vào các lớp học có sức chứa lớn nhất:
DECLARE @School TABLE (School_Id INT,Course_Id
VARCHAR(50), Total_Students INT)
DECLARE @Class TABLE (School_Id INT,Course_Id
VARCHAR(50), Class_ID VARCHAR(50), Capacity INT)
INSERT @School VALUES
(1, 'Acct101' ,150),
(1, 'Acct102' ,100),
(2, 'Acct101' ,110),
(2, 'Acct102' ,130)
INSERT @Class VALUES
(1, 'Acct101' ,'A1' ,65),
(1, 'Acct101' ,'A2' ,50),
(1, 'Acct101' ,'A3' ,70),
(1, 'Acct102' ,'Ab1' ,100),
(1, 'Acct102' ,'Ab2' ,100),
(2, 'Acct101' ,'B1' ,80),
(2, 'Acct101' ,'B2' ,90)
;WITH y AS (
SELECT a.*,
ROW_NUMBER() OVER
(PARTITION BY a.School_ID, a.Course_ID ORDER BY a.Capacity DESC)
CapacitiyOrderPerSchoolAndCourse,
SUM(a.Capacity) OVER
(PARTITION BY a.School_ID, a.Course_ID)
TotalCapacityForSchoolAndCourse,
b.Total_Students TotalParticipants
FROM @Class a
JOIN @School b ON
b.School_Id = a.School_Id
AND b.Course_Id = a.Course_Id
), z AS(
SELECT x.School_Id,
x.Course_Id,
y.TotalCapacityForSchoolAndCourse,
y.TotalParticipants,
CASE WHEN y.TotalParticipants < SUM(x.Capacity) THEN
y.TotalParticipants
ELSE
SUM(x.Capacity)
END NumberOfStudentsInClasses,
MIN(y.Capacity) ClassCapacity,
y.Class_ID ClassName,
MIN(y.Capacity) -
CASE WHEN y.TotalParticipants - SUM(x.Capacity) < 0 THEN
ABS(y.TotalParticipants - SUM(x.Capacity))
ELSE
0
END StudentsInClass
FROM y
JOIN y x ON x.School_Id = y.School_Id
AND x.Course_Id = y.Course_Id
AND x.CapacitiyOrderPerSchoolAndCourse
<= y.CapacitiyOrderPerSchoolAndCourse
GROUP BY x.School_Id,
x.Course_Id,
y.CapacitiyOrderPerSchoolAndCourse,
y.Class_ID,
y.TotalCapacityForSchoolAndCourse,
y.TotalParticipants
)
SELECT
z.School_Id,
z.Course_Id,
z.TotalCapacityForSchoolAndCourse,
z.TotalParticipants,
z.ClassName,
z.ClassCapacity,
CASE WHEN StudentsInClass < 0 THEN
0
ELSE
StudentsInClass
END StudentsInClass
FROM z
Nếu bạn muốn mỗi lớp học có một số học sinh, bạn có thể làm như thế này (nó phân bổ số lượng học sinh cho mỗi lớp học tùy theo sức chứa của nó):
;WITH y AS (
SELECT a.*,
SUM(a.Capacity) OVER
(PARTITION BY a.School_ID, a.Course_ID)
AS TotalCapacityForSchoolAndCourse,
b.Total_Students TotalParticipants
FROM @Class a
JOIN @School b ON
b.School_Id = a.School_Id
AND b.Course_Id = a.Course_Id
), z AS(
SELECT y.School_Id,
y.Course_Id,
y.TotalCapacityForSchoolAndCourse,
y.TotalParticipants,
MIN(y.Capacity) ClassCapacity,
y.Class_ID,
MIN(y.Capacity) * 1.0 / y.TotalCapacityForSchoolAndCourse
AS PercentOfCapacity,
ROUND(
MIN(y.Capacity) * 1.0 / y.TotalCapacityForSchoolAndCourse
* TotalParticipants
, 0, 0)
AS NumberOfStudents
FROM y
GROUP BY y.School_Id,
y.Course_Id,
y.Class_ID,
y.TotalCapacityForSchoolAndCourse,
y.TotalParticipants
)
, i AS(
SELECT
z.School_Id,
z.Course_Id,
z.TotalCapacityForSchoolAndCourse,
z.TotalParticipants,
z.Class_ID,
z.ClassCapacity,
PercentOfCapacity,
NumberOfStudents,
SUM(NumberOfStudents) OVER
(PARTITION BY z.School_Id, z.Course_Id)
AS SumNumberOfStudents,
ROW_NUMBER() OVER
(PARTITION BY z.School_Id, z.Course_Id
ORDER BY NumberOfStudents)
AS ClassWithSmallestCapacity
FROM z
), j AS(
SELECT i.School_Id,
i.Course_Id,
i.TotalCapacityForSchoolAndCourse,
i.TotalParticipants,
i.Class_ID,
i.ClassCapacity,
i.PercentOfCapacity,
i.NumberOfStudents,
i.NumberOfStudents +
CASE WHEN ClassWithSmallestCapacity = 1 THEN
TotalParticipants - SumNumberOfStudents
ELSE 0
END AS NumberOfStudents2
FROM i
)
SELECT *
FROM j