我应该如何在数据库中处理渐进式状态代码

本文关键字:处理 渐进式 状态 代码 数据库 我应该 | 更新日期: 2023-09-27 18:10:26

我正在为一个学术机构做一个项目,我需要关于解决这个问题的最佳方法的建议。我已经很长时间没有做任何传统的应用程序开发了(接近5年)。

学院管理部门最近修订了学院的学术标准政策。以前,政府只有三个状态码,所以这不是什么大问题。但是,新策略有六个状态码:

    有着良好信誉
  1. 学术关注
  2. 学术干预(1)
  3. 届解雇
  4. 学术干预(2)
  5. 篇解雇

从这里开始,我将用termGPA来区分学期GPA,用cumGPA来区分累积GPA。如果学生的学期gpa 低于2.0,并且导致他/她的综合gpa 也低于2.0,他/她将被置于学业关注名单。一旦关注学业,以下三种情况中的一种会发生在学生身上。他们:

  1. 如果他们的学期平均绩点和综合平均绩点上升到2.0以上,则恢复良好的信誉。
  2. 学期平均绩点在2.0以上,但综合平均绩点在2.0以下的,保持当前状态。
  3. 如果他们的学期gpa和cumGPA都低于2.0,则进入下一个状态。

通常情况下,我会通过编写一个控制台应用程序来处理每个学生,并在此过程中构建状态代码。然而,我们至少要处理8000名学生,在大多数情况下,每学期大约有12500名学生。

此外,该政策必须在一段尚未指定的时间内追溯应用(因为以前的学生可以返回学院,然后将受到新政策的限制),一旦我在数据集中包括一个学生,我必须回顾该学生在学院的整个历史。我保守地猜测,我将浏览至少一百万个学生的记录,并计算每个学生的学期gpa和滚动gpa。

问题:

    是否有任何方法处理这个问题在SQL和避免使用游标?
  1. (假设答案为1。是"否")我应该如何构建一个控制台应用程序?我应该在写入数据库之前创建一个大的集合并一次处理几千名学生,还是在每次处理每个学生之后更新数据库?
  2. 我是不是太小题大做了?

提前感谢您的意见和建议。


编辑:根据对这里答案的评论,我应该提供更多关于数据结构和我计算gpa的方式的信息。

我不能在我们的数据库中使用预先计算的cumGPA值——我需要学生在每个学期结束时的cumGPA,就像这样(注意:我在下面编造了GPA值):

ID      TermID  CumGpa  TermGPA TermNumber PolicyCode
123545  09-10-2  2.08   2.08      1         GoodStanding
123545  09-10-3  1.94   0.00      2         AcademicConcern
123545  09-10-4  1.75   1.00      3         AcademicIntervention
123545  10-11-2  1.88   2.07      4         AcademicIntervention
123545  10-11-4  2.15   2.40      5         GoodStanding
123545  11-12-1  2.30   2.86      6         GoodStanding

问题是,每个后续学期的状态码可能依赖于前一个学期的状态码——实际上,良好的信誉是唯一不依赖于前一个学期的状态码的。

据我所知,这意味着我必须在SQL中使用游标来获取每个学生的最新状态码,这不是我感兴趣的东西,因为我在一个资金紧张的大学工作,正好有三个数据库服务器:一个用于测试,两个服务器上有相同的数据(我们正在迁移到SQL Server 2008 R2的过程中)。

我应该如何在数据库中处理渐进式状态代码

真有意思。我认为您不必太担心SQL性能。对于您的应用程序,它将运行得相当快。我只是运行了一个愚蠢的小控制台应用程序来修复混乱,一次插入15000条记录。大约花了5秒钟。

首先,12,000条记录对于现在的数据库来说不算什么,所以这不是你的问题。你应该专注于保持简单。似乎你的数据库将经常基于事件,所以我建议使用触发器,即:当你的termGPA被插入时第一个触发器-更新cumGPA,第二个在cumGPA更新后-检查你的标准和更新状态,如果它们发生了。

即使SQL的免费版本现在也可以处理高达10gb的数据库。12,500条记录是很小的。在浏览100万条记录时,您应该遍历每个学生或组,以允许清除事务日志。这可以通过使用游标或控制台应用程序来实现。如果您可以在TSQL中执行计算,那么批处理它们可能会比一次一个更快。缺点是批处理越大,事务日志就越大,因此存在一个最佳点。如果计算对于TSQL来说太复杂,并且花费的时间几乎与插入语句一样长(或更长),您可以在单独的线程上插入(或在单独的线程上计算),这样插入和计算是并行的。我在一个应用程序中这样做,在这个应用程序中,我从文本中解析单词——解析大约需要插入单词的时间。但我不会让它出现多个正面。在SQL方面,它仍然需要维护索引,并且使用来自两个线程的插入会减慢它的速度。只有两个线程,较快的线程等待较慢的线程。更新的顺序也很重要。如果按照聚集索引的顺序进行处理,则更有可能该记录已经在内存中。

我最终用c#编写了一个控制台应用程序来处理这些状态码。我的用户更改了初始状态更新需求,只包括前两个术语,但是这个过程有足够多的边缘情况,所以我选择花时间编写更干净的面向对象代码,以便在此策略成熟和更改后更容易恢复(他说,希望如此)。

此外,我最终不得不将这个数据库部署到SQL 2005实例上,因此表值参数对我来说不可用。如果是这样的话,我就会选择在处理完每个学生之后才向数据库提交,而不是在处理完每个学生的每个学期之后。