SQL keeping count of how many times - mysql

I have a table of grades/courses. I am trying to see how many times a person has taken a course, and also return the highest grade they have achieved.
So far I have:
SELECT tnumber, courseid, grade FROM grades
I need to display all tnumbers that have taken the same course more than once. Also list the students highest grade for the course.
How do you keep count of how many times a course has occurred?
I want to display the student's tnumber, course_id, attempts, and highest grade. And all within a single query.
If I need to show an example of my table/s. Let me know and Ill post them. I just don't want to overload the page with code!
Thanks.

For example (table alias G not necessary as only 1 table is involved using for example only)
SELECT g.tnumber, g.courseid, min(g.grade), count(*)
FROM grades g
GROUP BY g.tNumber, g.CourseID
This returns the tnumber and courseID for each record with the highest (alphabetic grade) and a count of how many records exist for that same tnumber and courseID. You could use count(*) or count(1).
Based on a prior posts I'm assuming grade is alphabetic.

SELECT tnumber, courseid, COUNT(courseid) times_taken, MAX(grade) highest_grade FROM grades GROUP BY tnumber, courseid
This assumes that grade is a number.

Try this query (I assume grade is a number column):
select tnumber, course_id, count(course_id), max(grade)
from grades
group by tnumber, course_id

Related

Determine row number for entry in a sorted SQL table

Suppose I have a table storing say student information
id | first_name | last_name | dob | score
where score is some non-unique numeric assessment of their performance. (the schema isn't really relevant, I'm trying to go as generic as possible)
I'd like to know, for any given student, what their score-based overall ranking is. ROW_NUMBER() or any equivalent counter method doesn't really work since they're only accounting for returned entries, so if you're only interested in one particular student, it's always going to be 1.
Counting the number of students with scores greater than the current one won't work either since you can have multiple students with the same score. Would sorting additionally by a secondary field, such as dob work, or would it be too slow?
You should be able to JOIN into a subquery which will provide the ranks of each student across the entire population:
SELECT student.*, ranking.rank
FROM student
JOIN (
SELECT id, RANK() OVER (ORDER BY score DESC) as rank
FROM student
) ranking ON student.id = ranking.id
I suppose the scale of your data will be a key determinant of whether or not this is a realistic solution for your use case.

Is my solution to this SQL query correct?

In my exam we were given the following relations:
COURSES(**Number**, School, CourseName)
STUDENTS(**SNumber**, Surname, FirstName, School)
EXAMS(**Student**, **Course**, Grade, Date)
where the keys are in bold. The EXAMS relation stores information of students that passed an exam for a given course .EXAMS.Student references STUDENTS.SNumber and EXAMS.Course references COURSES.Number.
We wear asked to write one SQL query that retrieves all the following information for each student number:
-their surname
-how many different exams they passed
-how many different grades they obtained
-the minimum, average and maximum grade they obtained in their exams."
Firstly, I included in my answer that I noticed that, as EXAMS only stores information about a student who passed an exam, there is no way to know if a student failed an exam and so we could only count how many different pass grades they obtained. Here is the query I wrote:
SELECT S.SNumber, S.Surame,
COUNT(E.Student) AS NumberOfExamsPassed,
COUNT(DISTINCT E.Grade) AS NumberOfDifferentPassGrades,
MIN(E.Grade) AS MinimumGrade,
MAX(E.Grade) AS MaximumGrade,
AVG(E.Grade) AS AverageGrade
FROM Students S, EXAMS E
GROUP BY E.Student;
Would this be a sufficient solution?
You should use Explicit Joins.
SELECT S.SNumber, S.Surame,
COUNT(E.Student) AS NumberOfExamsPassed,
COUNT(DISTINCT E.Grade) AS NumberOfDifferentPassGrades,
MIN(E.Grade) AS MinimumGrade,
MAX(E.Grade) AS MaximumGrade,
AVG(E.Grade) AS AverageGrade
FROM Students S
INNER JOIN EXAMS E ON S.SNumber = E.Student
GROUP BY E.Student;

How to select all subjects that are taken by all students such that all students took grade > 50 in them

I have a table called records containing 3 columns: student, subject and grade
Each {x,y,z} entry in the table means student x took class y with grade z. If student x didn't take class y then the entry doesn't exist in the table. So this table is like a university record of all students and the subjects taken by them.
I want to select all subjects that are taken by all students such that the grades of all students in these subjects are above 60.
I tried creating the table
CREATE TABLE temp SELECT subject FROM records WHERE grade > 60;
Then I used temp to create a new table that has subject and count, where count counts the number of students that took that subject, and then I deleted all rows that have count< number of students. But I know this is very inefficient.
How can I do this more efficiently using MySQL ?
Also if you can provide me with good MySQL resource/tutorial link so that I can practice, I would be thankful. I am new to MySQL and I am working on large databases and I need to make my queries more efficient and straight forward.
How about
SELECT subject FROM records
WHERE subject NOT IN
(
SELECT subject FROM records
WHERE grade <=60
)
AND subject IN
(
SELECT subject FROM records
GROUP BY subject
HAVING count(*) = (SELECT COUNT(DISTINCT student) FROM records)
)
As further reading I'd recommend this and this
EDITED: now includes "subjects taken by ALL students"
I would use the no exists clause because it simply confirms if there are no records within the subquery, but will not try to obtain the resultset. It is more effective than a not in clause.
SELECT subject FROM records r1
WHERE subject NOT EXISTS
(
SELECT 1 FROM records r2
WHERE r2.subject=r1.SUBJECT AND grade<=60
)

MYSQL - Querying averages of ratings for multiple users in a single query

I am building a site one aspect of which involves teachers and rating teachers. Ratings are made by students, and when students are looking for teachers, among the criteria I'd like for them to be able to filter the teachers by include their average ratings.
Each rating by each student of each teacher puts the number of stars they rate the teacher into the database. I already have a query that can calculate the average stars for each teacher
SELECT AVG(star) AS Average FROM rating_table WHERE type = 'Member_review'
AND teacher_id = id_number
with id_number obviously being the user_id of the teacher.
When people are on the search page for all teachers, I'd love for them to be able to filter the teachers by rating, among other criteria. I can put this query in a foreach loop and have it run down each and every teacher id, but I suspect this will be a huge drag on the server - is there a way for me to put a string of comma-seperated ids into the query and have it find the average rating for each one? I did try this query and it did not work
SELECT AVG(star) AS Average FROM rating_table WHERE type = 'Member_review'
AND teacher_id IN(1,2,3, etc...)
Is there a way in which i can get the query to take the average for each teacher user_id and have it out put something like this?
Average Teacher ID
3.5 6
4.6 2
Yes. This is a basic aggregation query:
SELECT AVG(star) AS Average, teacher_id
FROM rating_table
WHERE type = 'Member_review' and
teacher_id IN(1,2,3, etc...)
group by teacher_id

Exercise Help - Select the register number of the students with the average highest score

I am studying SQL at my university, and I was practicing this exercise and got stuck! I have a database that stores all the exams passed by a student for a specific teach.
These are the tables in the database:
Student(**number**, name, birthday)
Exam(**student_number**, **teaching_code**, vote) *(store the exams passed by the students with vote)*
Teaching(**code**, name)
Where number is the primary key for the Student table, and code is for Teaching, "student_number" references "number" in Student, and "teaching_code" references "code" in Teaching.
The exercise asks to select the students’ numbers with the average highest score.
I know how to write a query which gives me a table containing the average for each students but I don't know how to select the highest from it or how to show the corresponding student number!
The solution with the limit command doesn't work if exists some students have the same highest average...
The query to show the average score per student is:
select avg(e.vote) as Average from STUDENT s, EXAM e
where s.number = e.student_number
group by s.number
EDIT:
I tried the MAX function in SQL, I have tried this:
select MAX( avg(e.vote) ) as Average from STUDENT s, EXAM e
where s.number = e.student_number
group by s.number
but it say "Error Code: 1111. Invalid use of group function"
Probably the solution is with a nested query but I can't realize it.
SELECT MAX(Expression)
FROM tables
WHERE Condition
You can check the documentation on how to use MAX and find highest value.
If you want to select the TOP 5 or 10 or 20... highest, use the TOP clause.
select student_code, MAX(avg_vote)
FROM (
SELECT student_code, AVG( vote) as avg_vote
FROM Exam
GROUP BY student_Code ) t
GROUP BY student_code
I didn't checked that query.
May query to select that max average is be like that
What a pity MySQL doesn't seem to support CTE's, then this would have been so simple.
select t.student_code, t.avg_vote
FROM (SELECT student_code, AVG(vote) as avg_vote
FROM Exam
GROUP BY student_Code) t
WHERE t.avg_vote = (select max(avg_vote)
FROM (SELECT student_code, AVG(vote) as avg_vote
FROM Exam
GROUP BY student_Code))
Continue studying hard, being presented with a likely answer is far less useful than actually reaching the conclusion yourself. Actually, if you're lucky, my proposal will not work (I haven't tested) so that you will have to come up with the right modification yourself!