2013-07-04 3 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

Если оценка идентификаторами являются последовательными для каждого студента, то простое соединение будет делать:

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 –

Смежные вопросы