在两列或更多列上基于代数对MySql中的行进行排序

时间:2014-01-31 13:23:09

标签: mysql sql sorting

我正在为学校设计一个测试系统。表格就像这样

------------------------------------------------------------------------------
    Student_id  | Total Questions  |     Questions Attempted   |    Correct     
------------------------------------------------------------------------------
     36         |       60         |           42              |       20      
     19         |       60         |           38              |       32
     119        |       60         |           37              |       31

现在,标记方案为+3表示正确,-1表示错误

错误问题的数量将计算为wrong = attempted - correct

问题

1)我想根据他们的等级给予学生一些积分,所以我想按照他们的分数i.e. score = 3 * correct - wrong的递减顺序对表格进行排序。虽然,我也可以存储得分但由于它是冗余数据,我不想将它存储到表中。如何使用SQL查询对表进行排序。

2)当我将学生的成绩根据他们的成绩更新到表student时,我从student_id表中选择result并更新{{1}表,即每个学生1个查询。这意味着如果有4000名学生参加考试,那么4000个查询! 。我可以改善情况(最小化查询)吗?

修改

问题2的学生模式

student

3 个答案:

答案 0 :(得分:3)

  1. 您只需在排序

    中指定所需内容即可
    select student_id,correct, attempted,field4,field5, (3 * correct - (attempted-correct)) as score 
    from students sort by score desc
    
  2. 是的,看看bulk update的sql,你可以准备查询并按10或100比100更新10,但不要太多,因为sql命令对其长度有限制

答案 1 :(得分:1)

问题1。

假设该表名为Results,并且该Student_id是唯一的,以下是您的问题的可能解决方案:

SELECT Results.*, (3*Correct-(Total_Questions-Correct)) AS score
FROM Results
ORDER BY score DESC

问题2。

假设学生已经添加到学生表中,或者他们已经有分数,这是一个可能的SQL查询来更新学生表而不进行4k查询:

UPDATE StudentsTable AS s
INNER JOIN PointsTable AS p
ON s.Student_id = p.Student_id
SET
    s.Points = s.Points + (3 * p.Correct - (p.Questions_Attempted - p.Correct))

如果将来需要执行更多测试,可以向Points Table添加Test_ID列,然后在UPDATE查询中添加WHERE子句,以便只添加给定测试的分数。

<强>优化

您可以通过更改计算分数的方式来优化查询:

SELECT Results.*, (2*Correct-Total_Questions) AS score
FROM Results
ORDER BY score DESC

UPDATE StudentsTable AS s
INNER JOIN PointsTable AS p
ON s.Student_id = p.Student_id
SET
    s.Points = s.Points + (2 * p.Correct - p.Questions_Attempted)

答案 2 :(得分:0)

按分数对学生进行排名

SELECT student_id,
(
  SELECT 1 + COUNT(*)
    FROM student_results
   WHERE 3 * correct - (total - correct) >=
         3 * r.correct - (r.total - r.correct)
     AND student_id <> r.student_id
) rank
  FROM student_results r

输出:

| STUDENT_ID | RANK |
|------------|------|
|         36 |    3 |
|         19 |    1 |
|        119 |    2 |

现在,您可以使用多表UPDATE语法一次性更新学生点数,而不是使用更新查询数量来访问数据库。

UPDATE students s JOIN
(
  SELECT student_id,
  (
    SELECT 1 + COUNT(*)
      FROM student_results
     WHERE 3 * correct - (total - correct) >=
           3 * r.correct - (r.total - r.correct)
       AND student_id <> r.student_id
  ) rank
    FROM student_results r
) q
    ON s.student_id = q.student_id
   SET s.points = s.points + 
       CASE q.rank  -- implement your logic of translating ranks to points here
          WHEN 1 THEN 100
          WHEN 2 THEN  50
          WHEN 3 THEN  10
          ELSE 0
       END;

这是 SQLFiddle 演示