sql - 计算加权分数内的加权分数
问题描述
我有一个一直在努力解决的数学/SQL 问题。
我有两个具有以下结构的表:
CREATE TABLE Exams
(
ExamID INT PRIMARY KEY,
ExamName VARCHAR(100),
CourseID INT,
RelatedExamID INT NULL,
Weighting DECIMAL (5,3)
)
CREATE TABLE ExamMarks
(
ExamMarkID INT IDENTITY PRIMARY KEY,
StudentID VARCHAR(8),
ExamID INT FOREIGN KEY REFERENCES Exams(ExamID),
ExamMark DECIMAL (5,4)
)
检查表包含以下数据:
INSERT INTO Exams (ExamID, ExamName, CourseID, RelatedExamID, Weighting)
VALUES (1, 'English',1,NULL,1),
(2, 'French',2,NULL,1),
(3, 'Maths',3,NULL,0.6),
(4, 'Statistics',3,NULL,0.4),
(5, 'Physics Part 1',4,NULL,0.5),
(6, 'Physics Part 2',4,NULL,0.5),
(7, 'Heat and Mass',4,6,0.25)
考试成绩表包含以下数据:
INSERT INTO ExamMarks (StudentID, ExamID, ExamMark)
VALUES ('00112233', 1, 0.75),
('00112233', 2, 0.52),
('00112233', 3, 0.68),
('00112233', 4, 0.8),
('00112233', 5, 0.50),
('00112233', 6, 0.66),
('00112233', 7, 0.45)
这里的想法是给定的课程可能有
- 单一考试(例如英语和法语)
- 具有独立权重的多项考试(例如课程 3,其中有 2 个名为“数学”和“物理”的考试)-在这种情况下,课程的结构使得数学考试占总考试的 60%,而物理考试贡献40%
- 带有子考试的考试,例如课程 4,稍后会详细介绍。
如果我想获得每个考试的每个候选人的加权总分 - 暂时忘记课程 4 - 我会执行以下操作:
SELECT em.StudentID,e.CourseID, SUM(em.ExamMark * e.Weighting)/SUM(e.Weighting)
FROM Exams e
INNER JOIN ExamMarks em ON e.ExamID = em.ExamID
GROUP BY em.StudentID,e.CourseID
但是,课程 4 由 3 个部分组成:
- 物理第 1 部分 - 总数的 50%,以及
- 物理第 2 部分 - 也是总数的 50%
- 热量和质量,占物理第 2 部分的 25%(因此其 ID 在“RelatedExamID”列中)
需要明确的是,热量和质量占物理第 2 部分的 25%,而物理第 2 部分本身占课程的 50%。
我已将这些数字放入 Excel 电子表格中,经过一番摸索后,我得出结论,我们的学生应该在课程 4 中获得 55.375% 的分数。
然而,不幸的是,我的 SQL(和数学/逻辑)技能不足以在 SQL 查询中得到这个结果。
上面的数据代表了某种简化。事实上,有大约 10000 分需要考虑(涉及大约 500 名学生),大约有 200 种不同的考试,其中可能有 30 种是“子考试”。考虑到这些权重,每年都必须将这些汇总起来,以便为学生提供每门课程的分数。
解决方案
好的,所以我设法找到了解决方案。我仍然会感谢那些比我了解更多的人可能更有效或更强大的任何其他人。
--Get SubComponent marks
WITH SubComponents
AS
(SELECT
em.StudentID
,em.ExamID
,e.RelatedExamID
,e.Weighting
,e.Weighting * em.ExamMark AS WeightedMark
FROM Exams e
INNER JOIN ExamMarks em
ON e.ExamID = em.ExamID
WHERE e.RelatedExamID IS NOT NULL),
--Get marks for those components which have subcomponents
ParentComponents
AS
(SELECT
em.StudentID
,e.CourseID
,em.ExamID
,e.RelatedExamID
,e.Weighting
,((1 - SubComponents.Weighting) * em.ExamMark)
+ SubComponents.WeightedMark AS OverallComponentMark
FROM Exams e
INNER JOIN ExamMarks em
ON e.ExamID = em.ExamID
INNER JOIN SubComponents
ON SubComponents.RelatedExamID = e.ExamID
AND SubComponents.StudentID=em.StudentID),
--Get marks for those components which are neither parent nor child components
StandaloneComponents
AS
(SELECT
em.StudentID
,e2.CourseID
,em.ExamID
,e2.RelatedExamID
,e2.Weighting
,em.ExamMark
FROM Exams e2
INNER JOIN ExamMarks em
ON e2.ExamID = em.ExamID
WHERE NOT EXISTS (SELECT
*
FROM Exams
WHERE RelatedExamID = e2.ExamID)
AND e2.RelatedExamID IS NULL),
-- Bring all the above together
ComponentMarks
AS
(SELECT
StudentID
,CourseID
,ExamID
,Weighting
,ExamMark
FROM StandaloneComponents
UNION
SELECT
StudentID
,CourseID
,ExamID
,Weighting
,OverallComponentMark
FROM ParentComponents)
-- Finally group and combine marks at course level
SELECT
StudentID
,CourseID
,SUM(ExamMark * Weighting) / SUM(Weighting)
FROM ComponentMarks
GROUP BY StudentID
,CourseID
推荐阅读
- java - 验证代理的 Java Bean 不会与正确的值进行比较
- javascript - 我想显示基于类别(在给定的示例爱好中)的用户列表。寻找基于javascript的解决方案
- android - Android Studio 设备中的 Android Google 身份验证错误
- ansible - Ansible Tower - 是否可以在通知中显示调查变量
- shell - Grep 并不总是从文件中找到正确的值
- c++ - C++ OpenCV VideoWriter 帧率同步
- php - 如何将数组数据插入文件?
- javascript - 如果另一个下拉菜单打开,我如何关闭下拉菜单
- entity-framework-core - 是否可以在 EF Core 的 OnModelCreating 中为 CosmosDB 容器设置 TTL?
- c - SDL2:IMG_Load() - Raspberry Pi 上的分段错误