2013-07-04 37 views
1

被預先警告:我是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

你陷害的問題非常好。閱讀愉快。做得好。 – Mari

回答

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 
+0

+1包括一個解決方案,它不是基於每個學生的score_id連續的事實 – Stephan

+0

不,這是不連續的。我會更新我的例子來證明這一點。 –

+0

這效果很好。不幸的是,我只是意識到我將日期保存在相關表格中。哦,我會讓它工作。 –

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 
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 

fiddle this

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不喜歡分區的東西。編輯我的查詢,所以不使用它。

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 

sqlfiddle

+0

它將從20到20的更改返回爲-1 –