为SQL中的分数更改设置标志

为SQL中的分数更改设置标志,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一张不同星期的考试成绩表。我想用分数差创建一个额外的列,比如如果分数减少0-5,然后是1,5-9,然后是2,10+然后是3,如果分数增加,然后是4。这是我在表格中的样本数据 --DROP TABLE #Scores CREATE TABLE #Scores ( NAME varchar(10), Grade varchar(10), Subject varchar(25), Exam_Date datetime, Score int ) INSERT

我有一张不同星期的考试成绩表。我想用分数差创建一个额外的列,比如如果分数减少0-5,然后是1,5-9,然后是2,10+然后是3,如果分数增加,然后是4。这是我在表格中的样本数据

--DROP TABLE #Scores
CREATE TABLE #Scores (
    NAME varchar(10),
    Grade varchar(10),
    Subject varchar(25),
    Exam_Date datetime,
    Score int
)

INSERT INTO #Scores
    VALUES ('Sam', 'XI', 'Maths', '2016-08-01 15:47:29.533', 38), 
           ('Sam', 'XI', 'Maths', '2016-07-25 15:47:29.533', 50), 
           ('Mike', 'XI', 'Maths', '2016-08-01 15:47:29.533', 50), 
           ('Mike', 'XI', 'Maths', '2016-07-25 15:47:29.533', 45)

SELECT * FROM #Scores
非常感谢您将使用
lag()
case

select s.*,
       (case when score - prev_score < 0 then 4
             when score - prev_score <= 5 then 1
             when score - prev_score <= 9 then 2
             else 3
        end) as score_diff
from (select s.*,
             lag(score) over (partition by name, subject order by exam_date) as prev_score
      from #scores s
     ) s;
s.*,
(如果分数-上一次分数<0,则为4
当分数-上一个分数时,您将使用
lag()
case

select s.*,
       (case when score - prev_score < 0 then 4
             when score - prev_score <= 5 then 1
             when score - prev_score <= 9 then 2
             else 3
        end) as score_diff
from (select s.*,
             lag(score) over (partition by name, subject order by exam_date) as prev_score
      from #scores s
     ) s;
s.*,
(如果分数-上一次分数<0,则为4

当分数-上一个分数时,考虑进一步的标准化步骤。将分数保存在单独的表中。将学生与分数表关联


您必须决定如何引用上一个分数以与当前分数进行比较。如果您创建了一个附加字段来存储上一个分数的更改,那么您可以使用一个显示当前分数的计算字段,或者将上一个分数存储在新分数旁边的字段中,然后使用一个显示当前分数的计算字段两者之间的距离。

考虑进一步的标准化步骤。将分数保存在单独的表中。将学生与分数表关联起来


您必须决定如何引用上一个分数以与当前分数进行比较。如果您创建了一个附加字段来存储上一个分数的更改,那么您可以使用一个显示当前分数的计算字段,或者将上一个分数存储在新分数旁边的字段中,然后使用一个显示当前分数的计算字段两者之间的差异。

多亏了@Gordon Linoff,我稍微修改了代码。逻辑是正确的,只是稍微修改一下数学

select s.*,
       (case when score - prev_score > 0 then 4
             when score - prev_score between -5 and 0 then 1
             when score - prev_score between -9 and -5 then 2
             else 3
        end) as score_diff
from (select s.*,
             lag(score) over (partition by name, subject order by exam_date) as prev_score
      from #scores s
     ) s;
结果已捕获,如下所示:


多亏了@Gordon Linoff,我对代码做了一点修改。逻辑是正确的,只需稍微修改一下数学即可

select s.*,
       (case when score - prev_score > 0 then 4
             when score - prev_score between -5 and 0 then 1
             when score - prev_score between -9 and -5 then 2
             else 3
        end) as score_diff
from (select s.*,
             lag(score) over (partition by name, subject order by exam_date) as prev_score
      from #scores s
     ) s;
结果已捕获,如下所示:



Gordon,谢谢你的回复,但这并没有给我我想要的分数数据-上一个分数,我想这不是正确的逻辑,因为如果分数小于上一个分数,我们得到的是一个负值,逻辑认为它小于零。例如(当前scor(30)-上一个分数(50))不是给标志3,而是给我4。@user331133…这就是你的问题的措辞。也许你真的想按另一个顺序做减法。戈登,谢谢你的回答,但这并没有给我我想要的分数数据-上一个分数,我想这不是正确的逻辑,因为如果分数小于t前一个分数我们得到的是一个负性值,逻辑上认为它小于零。例如(当前scor(30)-前一个分数(50))不是给标志3,而是给了我4。@user331133…这就是你的问题的措辞。不过,也许你真的想按其他顺序做减法。如果需要,我很乐意添加一些额外的列。额外的列是可以的,但是,如果你能从计算中得出列的值,请先这样做所有事情都是一样的。换句话说,如果你知道上一个和新的分数,那么你应该计算差异。原因是,如果你更新分数字段,你还必须记住更新更改字段。如果它是计算的,那么也不需要更新。你的数据很可能保持正确。如果需要。额外的列是可以的,但是,如果您可以从计算中得出列的值,那么在所有条件相同的情况下首先这样做。换句话说,如果您知道以前的分数和新的分数,那么您应该计算差异。原因是,如果您更新分数字段,您还必须记住更新更改字段。如果我经过计算,也不需要更新。数据保持正确的可能性更大。提示:使用适当的软件(MySQL、Oracle、DB2等)标记数据库问题很有帮助和版本,例如,
sql-server-2014
。语法和功能的差异通常会影响答案。提示:使用适当的软件(MySQL、Oracle、DB2等)标记数据库问题很有帮助和版本,例如
sql-server-2014
。语法和功能的差异通常会影响答案。如果您不确定,
case
条件总是按顺序搜索的。我相信这就是您必须重新排列它的原因。@shawnt00抱歉,我不明白。为什么我必须重新排列它。是的,case条件总是如此按顺序弓形排列,但由于两者之间没有重复项,这没关系。没关系。我只是浏览了一下戈登的答案。我以为他就是有这个问题的人,但我发现实际上只是减法后符号的差异。实际上我以为你是在发布你自己问题的答案。我可能应该多花点钱注意。
案例
条件总是按顺序搜索,以防你对此不确定。我相信这就是你必须重新安排它的原因。@shawnt00对不起,我不明白。为什么我必须重新安排它。是的,案例条件总是按顺序搜索,但因为两者之间没有重复,没关系。没关系。我只是想知道我对Gordon的答案感到惊讶。我以为他就是那个有这个问题的人,但我发现这实际上只是减法后符号的差异。事实上我以为你在发布你自己问题的答案。我可能应该更加注意。