预先警告:我是MySQL的新手,所以期待愚蠢的后续问题。
我正在编写一个跟踪学生考试成绩的应用程序。每个学生将在不同时间进行多项考试。我希望能够计算同一学生两次连续考试之间考试成绩的变化。这是我桌子的基本结构......
--------------------------------------------
| score_id | student_id | date | score |
--------------------------------------------
| 1| 1| 2011-6-1 | 15 |
| 21| 1| 2011-8-1 | 16 |
| 342| 1| 2012-3-1 | 18 |
| 4| 2| 2011-6-1 | 21 |
| 16| 2| 2011-8-1 | 20 |
| 244| 2| 2012-3-1 | 20 |
--------------------------------------------
我想从查询中返回的内容是......
---------------------
| score_id | growth |
---------------------
| 1| NULL|
| 21| 1|
| 342| 2|
| 4| NULL|
| 16| -1|
| 244| 0|
---------------------
这与被问及 here 的问题类似,但日期并不总是彼此分开的特定时间。
答案 0 :(得分:1)
如果每个学生的分数ID是连续的,那么简单的联接将会:
select s.score_id, s.score - sprev.score
from scores s left outer join
scores sprev
on s.student_id = sprev.student_id and
s.score_id = sprev.score_id + 1;
但是,如果输入数据实际上如此有序,我会感到惊讶。在这种情况下,您需要找到以前的学生分数。我认为相关子查询是最清楚的写法:
select score_id, score - prevscore
from (select s.*,
(select score
from scores s2
where s.student_id = s2.student_id and
s.date > s2.date
order by date desc
limit 1
) as prevscore
from scores s
) s
答案 1 :(得分:0)
这是非常低效的,不确定它是否可以优化,但我不知道你怎么能做你想要的,而不是每行发现额外的查询,但我没有花很多时间考虑优化路线,所以这只是一个解决方案,而不是最佳解决方案
SELECT score_id, (score-(SELECT score FROM table AS tbl2 WHERE tbl2.student_id=1 AND tbl2.score_id < tbl1.score_id ORDER BY tbl2.score_id DESC LIMIT 1)) AS growth FROM table as tbl1 WHERE tbl1.student_id=1
答案 2 :(得分:0)
试试这个
SELECT t1.score_id, t1.score - t2.score AS Growth
FROM Table1 t1
LEFT JOIN Table1 t2 on t1.score_id = t2.score_id + 1 and t1.student_id = t2.student_id
答案 3 :(得分:0)
这将是一个复杂的查询(虽然并非不可能 - 请参阅其他答案)。对于这些事情,我希望读取数据的发生更多,然后添加。因此,我会将最复杂的部分放在添加功能
中如果您可以控制数据库的外观,我建议您在分数数据库中添加一个额外的列:
------------------------------------------------------------
| score_id | prev_score_id | student_id | date | score |
------------------------------------------------------------
| 1| NULL | 1| 2011-6-1 | 15 |
| 2| 1 | 1| 2011-8-1 | 16 |
| 3| 2 | 1| 2012-3-1 | 18 |
| 4| NULL | 2| 2011-6-1 | 21 |
| 5| 4 | 2| 2011-8-1 | 20 |
| 6| 5 | 2| 2012-3-1 | 20 |
------------------------------------------------------------
添加新得分记录时,您可以轻松找到prev_score_id:
select score_id
from score
where studentId = :studentId
and date = ( select max(date)
from score
where studentId = :studentId
and date < :date )
现在,您的查询变得更加容易:
select current.score_id, current.score - previous.score as growth
from score current
left join score previous on current.prev_score_id = previous.score_id
编辑:刚才注意到mysql并不喜欢分区。编辑了我的查询,因此没有使用它。
答案 4 :(得分:0)
你走了,
SELECT STUDENT.SCORE_ID,TABLE1.CALSCORE FROM STUDENT LEFT OUTER JOIN
(SELECT S2.SCORE_ID,MIN(CASE WHEN S1.SCORE=S2.SCORE THEN NULL
ELSE (S2.SCORE - S1.SCORE) END) CALSCORE
FROM STUDENT S1 INNER JOIN STUDENT S2
ON S1.student_id=S2.student_id
AND S1.DATE1 < S2.DATE1 AND S1.SCORE_ID < S2.SCORE_ID
GROUP BY S2.SCORE_ID) TABLE1 ON
STUDENT.SCORE_ID=TABLE1.SCORE_ID