用一些特殊情况计算查询

Posted

技术标签:

【中文标题】用一些特殊情况计算查询【英文标题】:Calculate query with some special case 【发布时间】:2021-02-17 01:55:25 【问题描述】:

我有一张桌子

考试(studentID、subjectCode、examDate、examScore)

还有很多类似的值

INSERT [dbo].[Exam] ([studentID], [subjectCode], [examDate], [examScore]) VALUES (N'ST01', N'PRJ', CAST(0x253C0B00 AS Date), 5)
INSERT [dbo].[Exam] ([studentID], [subjectCode], [examDate], [examScore]) VALUES (N'ST01', N'WIG', CAST(0x253C0B00 AS Date), 1)
 . . .
INSERT [dbo].[Exam] ([studentID], [subjectCode], [examDate], [examScore]) VALUES (N'ST09', N'WIG', CAST(0x253C0B00 AS Date), 4)
INSERT [dbo].[Exam] ([studentID], [subjectCode], [examDate], [examScore]) VALUES (N'ST09', N'WIG', CAST(0x263C0B00 AS Date), 9)
INSERT [dbo].[Exam] ([studentID], [subjectCode], [examDate], [examScore]) VALUES (N'ST10', N'MAD', CAST(0x253C0B00 AS Date), 3)
INSERT [dbo].[Exam] ([studentID], [subjectCode], [examDate], [examScore]) VALUES (N'ST10', N'MAE', CAST(0x253C0B00 AS Date), 4) 

我必须计算学生的所有平均分数,这样:(对不起,可怕的格式)

s_i 是第 i^th 个学生的平均分数,其中 i=1…M 其中 M 是学生总数 N是受试者的总数。 学生s_i的平均分可以通过以下方式计算:

其中 x_(i,k) 是学生 s_i 在主题 k^th 上的最后一次考试成绩。 最后一次考试的分数是指:学生可以重考,平均分计算只涉及最终成绩。 如果学生 s_i 没有参加第 k^th 科目的考试,x_(i,k) 可能会收到 Null 值。

我只能做类似的事情

select studentID, sum(examScore)/count(subjectCode) from Exam group by studentID

下半年这些特殊情况如何处理?

【问题讨论】:

【参考方案1】:

据我了解您的问题,您需要每个学生的平均分,仅考虑每个科目的最新分数。如果是这样,您可以使用窗口函数进行过滤,然后进行聚合:

select studentid, avg(examscore) avgscore
from (
    select e.*, 
        row_number() over(partition by studentid, subjectcode order by examdate desc) rn
    from exam e
) e
where rn = 1
group by studentid

如果你想把“缺失”的主题算作0,那就有点复杂了。您通常会cross join 列出不同的学生和科目,然后将表格与left join 一起提交:

select st.studentid, avg(coalesce(e.examscore, 0)) avgscore
from (select distinct studentid from exam) st
cross join (select distinct subjectcode from exam) su
left join (
    select e.*, 
        row_number() over(partition by studentid, subjectcode order by examdate desc) rn
    from exam e
) e 
    on  e.studentid   = st.studentid 
    and e.subjectcode = su.subjectcode 
    and e.rn = 1
group by st.studentid

在现实生活中,您可能会使用单独的引用表来存储学生和科目,而不是 select distinct_ 子查询。

【讨论】:

非常感谢!至少经过几次搜索,我现在可以理解您的方法。关于“is Null then 0”部分,我该如何正确地做到这一点?

以上是关于用一些特殊情况计算查询的主要内容,如果未能解决你的问题,请参考以下文章

SQL计算特殊情况下的百分比

在不使用子查询的情况下使用 SELECT DISTINCT ON 计算总行数

要查询book表中所有书名中包含“计算机”的书籍情况,可用 啥语句?

第14条:尽量用异常来表示特殊情况,而不要返回Nono

mybatis之特殊查询

性能优化之基础资源cpu&内存(JVM)