I want to get the list of students from db, who have get maximum number in each class with student name. Using MySQL DB.
I have the following tables like Student, classes, result (with different years results)
Tables structure student(student_id,student_name,class_id,address), class(class_id,class_name), results(result_id,student_id,year,marks)
and I need list like
Student Name class Marks
Jon A-1 800
Steve B-1 789
Edit corrected code, comment was correct
Try the code on this SQL Fiddle link
You could use a subquery to filter the students with the highest mark per class:
select s.student_name
, c.class_name
, r.marks
from results r
join student s
on r.student_id = s.student_id
join class c
on c.class_id = s.class_id
where r.result_id =
(
select r2.result_id
from student s2
join results r2
on s2.student_id = r2.student_id
where c.class_id = s2.class_id
order by
r2.marks desc
limit 1
)
Live example at SQL Fiddle.
select s1.student_name, c1.class_name, r1.marks
from student s1, class c1, results r1,
(select s2.class_id, max(r2.marks) marks
from results r2, student s2
where r2.student_id = s2.student_id
group by s2.class_id) agg
where r1.marks = agg.marks
and r1.student_id = s1.student_id
and s1.class_id = c1.class_id
and s1.class_id = agg.class_id
Related
I have to find student names who are enrolled in a class AND also in another class. But when I do a WHERE statement it cuts out out all the other lines that have the other classes.
So my question is: How would I go about doing it so that it compares the entire group and only selects students that are both in CLASSA and CLASSB.
Some of the students are in CLASSA and some of them are in CLASSB and some are in both. How do I get the one that is in both?
For example:
John Smith is in CLASSA
BETTY WHITE is in CLASSB
Timmy Edwards is in CLASSA
Timmy Edwards is in CLASSB
If I use an OR, it will select all of the names. But I only want a student that is in BOTH classes. So Timmy Edwards is the one I want selected.
WHERE C.DESCRIPTION LIKE 'Systems Analysis%'
AND C.DESCRIPTION LIKE 'Project Management%'
You can do use group by and having:
select student
from enrollments
where class in ('CLASSA', 'CLASSB')
group by student
having count(*) = 2;
This version assumes that a student can be enrolled only once for a given class.
No individual row will every have information for both classes. That means that AND and OR as you're using them are useless. You need to check for the existence of such rows using the EXISTS keyword.
select distinct
student
from
enrollments
where
exists (
select
1
from
enrollments e1
where
e1.student = enrollments.student
and e1.class = 'CLASSA'
) and exists (
select
1
from
enrollments e2
where
e2.student = enrollments.student
and e2.class = 'CLASSB'
)
Note:
Each row will have the student name in it, so I've added the DISTINCT keyword to remove the duplicates.
You could try something like this, (although im not sure what exactly your schema is like...)
WITH a AS
(
SELECT
S.FIRST_NAME||' '||S.LAST_NAME [Student]
,C.DESCRIPTION
FROM STUDENT S
JOIN ENROLLMENT E ON (E.STUDENT_ID = S.STUDENT_ID)
JOIN SECTION SE ON (SE.SECTION_ID = E.SECTION_ID)
JOIN COURSE C ON (C.COURSE_NO = SE.COURSE_NO)
WHERE C.DESCRIPTION = 'CourseA'
)
,b AS
(
SELECT
S.FIRST_NAME||' '||S.LAST_NAME [Student]
,C.DESCRIPTION
FROM STUDENT S
JOIN ENROLLMENT E ON (E.STUDENT_ID = S.STUDENT_ID)
JOIN SECTION SE ON (SE.SECTION_ID = E.SECTION_ID)
JOIN COURSE C ON (C.COURSE_NO = SE.COURSE_NO)
WHERE C.DESCRIPTION = 'CourseB'
)
Select a.Student, a.Description [DescA], b.Description [DescB]
from a join b on a.Student = b.Student
--optional where to just get students in both classes...
where a.Description is not null and b.Description is not null
Hope this assists...
You can always try the neat trick of joining a SELECT result with itself and then selecting from that result.
SELECT A.NAME
FROM (SELECT S.FIRST_NAME||' '||S.LAST_NAME as NAME,
S.STUDENT_ID as S_ID,
C.DESCRIPTION as DESC
FROM STUDENT S
JOIN ENROLLMENT E ON (E.STUDENT_ID = S.STUDENT_ID)
JOIN SECTION SE ON (SE.SECTION_ID = E.SECTION_ID)
JOIN COURSE C ON (C.COURSE_NO = SE.COURSE_NO)) A
JOIN (S.STUDENT_ID as S_ID, C.DESCRIPTION as DESC
FROM STUDENT S
JOIN ENROLLMENT E ON (E.STUDENT_ID = S.STUDENT_ID)
JOIN SECTION SE ON (SE.SECTION_ID = E.SECTION_ID)
JOIN COURSE C ON (C.COURSE_NO = SE.COURSE_NO)) B
ON A.S_ID = B.S_ID
WHERE A.DESC LIKE 'Systems Analysis%'
AND B.DESC LIKE 'Project Management%'
GROUP BY A.NAME
I'm working on a project where teachers can assign badges to students, it's similar to an achievement system.
Now I'm trying to get an overview of students who DON'T have a specific badge, but the queries I use are not working.
I made a table called StudentHasBadge, in which the studentnumber and badge_id are saved.
Example:
I want to show a list of students (s.studentnumber, s.firstname, s.lastname) that doens't have the "English: Reading" badge.
I use the following query:
(English: Reading has badge_id 61 in my database)
SELECT DISTINCT s.studentnumber, s.firstname, s.lastname
FROM students s INNER JOIN student_has_badge shb
ON s.studentnumber = shb.studentnumber
WHERE NOT shb.badge_id = 61
As results I also get students who earned the badge
I also tried != instead of WHERE NOT, but it doesn't give me a different result
You can use a LEFT JOIN and check for no match:
SELECT s.studentnumber, s.firstname, s.lastname
FROM students s LEFT JOIN
student_has_badge shb
ON s.studentnumber = shb.studentnumber AND shb.badge_id = 61
WHERE shb.studentnumber IS NULL;
You should use NOT EXISTS:
SELECT s.studentnumber, s.firstname, s.lastname
FROM students s
WHERE NOT EXISTS(SELECT 1 FROM student_has_badge
WHERE studentnumber = s.studentnumber
AND badge_id = 61);
Don't need the word NOT. Just the parameter of <> or =!
SELECT DISTINCT s.studentnumber,
s.firstname,
s.lastname
FROM students s
JOIN student_has_badge shb ON s.studentnumber = shb.studentnumber
WHERE
shb.badge_id <> 61
I want to get the amount of students who have passed ALL their subjects (mark >= 4).
Ex:
Student 1(OK):
Math: 5
Chemistry: 4
Student 2(OK):
Philosophy: 7
Student 3(NOT OK):
Math: 3
Philosophy: 6
Student 4(NOT OK):
Math: null
Philosophy: 8
DB:
-students(id)
-subjects_students(id_subject, id_student, mark)
SQL (using MySQL):
SELECT count(ss.id_student)
FROM subjects_students ss
WHERE (SELECT count(ss.id_student)
FROM students st
WHERE ss.id_student = st.id)
=
(SELECT count(ss.id_student)
FROM students st
WHERE ss.id_student = st.id
AND ss.mark >= 4)
I can´t seem to get the right amount. I get students who have passed some subjects, but not all of them.
EDIT: mark can be null. Do not count these.
ANSWER:
SELECT COUNT(*)
FROM
(
SELECT COUNT(ss.id_student)
FROM subjects_students ss
GROUP BY ss.id_student
HAVING MIN(ss.mark) >= 4 AND COUNT(ss.mark) = COUNT(*)
) src;
If you want students who have passed all their subjects, then you want to filter out the ones whose mark is too low. Here is one method:
SELECT ss.id_student
FROM subjects_students ss
GROUP BY ss.id_student
HAVING MIN(ss.mark) >= 4;
You can then count the students using this as a subquery.
Note that the join to the students table is unnecessary. All the information you need is in subjects_students.
This should join the students and subject table, then remove any students who have a subject with a failing grade.
SELECT
a.`id`,
c.`id_subject`,
c.`mark`
FROM `students` a
LEFT JOIN `subjects_students` c
ON a.`id` = b.`id_student`
LEFT JOIN `subjects_students` b
ON a.`id` = b.`id_student` AND b.`mark` < 4
WHERE b.`id` IS NULL
GROUP BY a.`id`,c.`id_subject`,c.`mark`;
I do like Gordon's method here is another that might be slightly slower but can get you to the count of students in the same query without 2 steps.
SELECT COUNT(DISTINCT ss.id_student) as CountOfStudents
FROM
subjects_students ss
WHERE
NOT EXISTS (SELECT 1 FROM subjects_students ss2 WHERE ss.id_student = ss2.id_student AND ss2.mark < 4)
Using table below
http://i.imgur.com/rIMgFZC.png
How do i display the names of toys that processed by Female Employees who are in level 3, level 4, and level 5 (not level 1 or 2) and a list of all toys’ name with stores’ postcode 10005. Write using union.
SELECT Toy_name
FROM Toy T
INNER JOIN hire_transaction H on T.toy_id = H.toy_id
INNER JOIN Employee E on H.E_id = E.E_id
WHERE E_Sex = ‘F’
AND E_Level between ‘3’ and ‘5’
UNION
SELECT Toy_name, Store_id
FROM Toy T, Store S
WHERE T.Store_ID IN(
SELECT Store_ID
FROM STORE S
WHERE Store_Postcode = ‘10005’);
this is my attempt. am i correct?
SELECT Toy_name
FROM Toy T
INNER JOIN hire_transaction H on T.toy_id = H.toy_id
INNER JOIN Employee E on H.E_id = E.E_id
WHERE E_Sex = 'F'
AND E_Level between 3 and 5
UNION
SELECT Toy_name
FROM Toy T
WHERE T.Store_ID IN(
SELECT Store_ID
FROM STORE S
WHERE Store_Postcode = '10005');
When using unions the distinct selects must have the same number and types of columns.
Removed the unnecessary implicit join in your second query.
You used the wrong quotation marks, inserted the single quotes.
I am using mysql to perform queries. have the following 7 tables.
appointment //non-atomic, eg. values -> 1,7,3
gender //atomic value
module //non-atomic, eg. values -> 12,33
program
rank
staff
student
I have tried 'concat', 'find_in_set' & 'in' functions but cannot get it to work. How may I display multiple values # relations 'appointment' & 'module'?
The following statement is the closest i can get. Please let me know if additional details are required, thank you.
SELECT sta.staName
, r.rank
, sta.appointmentID
, a.appointment
, m.moduleCode
FROM staff AS sta
JOIN rank AS r
ON (sta.rankID = r.rankID)
JOIN appointment AS a
ON (sta.appointmentID = a.appointmentID)
JOIN module AS m
ON (sta.teachModuleID = m.moduleID)
WHERE sta.genderID = 1;
SELECT sta.staName, r.rank, sta.appointmentID,
group_concat(distinct a.appointment) as appointments,
group_concat(distinct m.moduleCode) as moduleCodes
FROM staff AS sta
INNER JOIN rank AS r ON sta.rankID = r.rankID
INNER JOIN appointment AS a ON find_in_set(sta.appointmentID, a.appointmentID) > 0
INNER JOIN module AS m ON find_in_set(sta.teachModuleID, m.moduleID) > 0
WHERE sta.genderID = 1
GROUP BY sta.staName, r.rank, sta.appointmentID