Reputation: 8278
I am designing a Test-System for a school.The table is like this
------------------------------------------------------------------------------
Student_id | Total Questions | Questions Attempted | Correct
------------------------------------------------------------------------------
36 | 60 | 42 | 20
19 | 60 | 38 | 32
119 | 60 | 37 | 31
Now, marking scheme is +3
for correct and -1
for wrong
Number of wrong questions will be calculated as wrong = attempted - correct
Questions
1) I want to give the give the student some points based on their ranks, so I want to sort the table on the decreasing order of their score i.e. score = 3 * correct - wrong
.Though,I could have stored the score as well but since it is redundant data I don't want to store it into the table.How can I sort the table using SQL query.
2)When I will be updating the points of students based on their performance into the table student
,I am picking student_id
from result
table and making updations into the student
table i.e. 1 query per student.This means that if 4000 students sat for the test ,4000 queries !!! .Can I improve the situation (minimise queries)?
EDIT
Student schema for question 2
------------------------------------------------------------------------------
Student_id | fname | lname | contact | points
------------------------------------------------------------------------------
Upvotes: 0
Views: 75
Reputation: 303
Question 1.
Supposing the table is named Results, and that Student_id is unique, here is a possible solution to your question:
SELECT Results.*, (3*Correct-(Total_Questions-Correct)) AS score
FROM Results
ORDER BY score DESC
Question 2.
Supposing the Students are already added to the table Students, or that they already have a score, this is a possible SQL Query to update the students table without making the 4k queries:
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))
If you need to perform more tests in the future you can add a Test_ID column to you Points Table and then add a WHERE clause to the UPDATE query in order to just add up the score from a given test.
Optimization
You can optimize the queries a little bit by changing the way you calculate the score:
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)
Upvotes: 1
Reputation: 92795
To rank students by score you can do
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
Output:
| STUDENT_ID | RANK | |------------|------| | 36 | 3 | | 19 | 1 | | 119 | 2 |
Now you can update student points in one go using multi-table UPDATE
syntax instead of hitting the database with number of update queries.
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;
Here is SQLFiddle demo
Upvotes: 0
Reputation: 8652
you can just specify what you want in the sort
select student_id,correct, attempted,field4,field5, (3 * correct - (attempted-correct)) as score
from students sort by score desc
yes, take a look at bulk update of sql, you can prepare the query and update 10 by 10 or 100 by 100, but not too much since sql command have limit on its length
Upvotes: 3