I have below tables:
1. school
- id
- name
2. grade
- id
- name
-school_id
3. class
- id
- name
- grade_id
4. student
- id
- name
- class_id
5. donation
- id
- amount
- student_id
I want to get get no.of grade,class,student,donation per school I have tried this query
SELECT school.id AS ID, school.name AS Name,COUNT(student.id) AS
Students,COUNT(class.id) AS Class,COUNT(grade.id) AS Grade
FROM (((
INNER JOIN class ON student.classId=class.id )
INNER JOIN grade ON class.gradeId=grade.id)
INNER JOIN school ON grade.sclId=school.id)
GROUP BY ID;
but it returns wrong result. spend enough time for this but not getting any solution.can any one help?
You can try the following query without those parentheses. And you also need to include the non-aggregated
column sc.name
in the group by
list. By the way consider using LEFT JOIN
even if a student has non-matched data for at least one of the other three tables :
SELECT sc.id AS ID,
sc.name AS Name,
COUNT(st.id) AS Students,
COUNT(c.id) AS Class,
COUNT(g.id) AS Grade
FROM student s
LEFT JOIN class c ON c.id = s.classId
LEFT JOIN grade g ON g.id = c.gradeId
LEFT JOIN school sc ON sc.id = g.sclId
GROUP BY sc.id, sc.name;
You can try the following query
SELECT sc.Id, sc.Name
, SUM(CASE WHEN g.Id IS NOT NULL THEN 1 ELSE 0 END ) AS Grade
, SUM(CASE WHEN c.Id IS NOT NULL THEN 1 ELSE 0 END ) AS Class
, SUM(CASE WHEN s.Id IS NOT NULL THEN 1 ELSE 0 END ) AS Students
FROM School AS sc
LEFT OUTER JOIN Grade AS g ON sc.Id = g.sclId
LEFT OUTER JOIN Class AS c ON g.Id = c.GradeId
LEFT OUTER JOIN Student AS s ON c.Id = s.classId
GROUP BY sc.Id, sc.Name
You have joins along multiple dimensions, so the rows are getting multiplied by the joins. There are two ways to handle the counting. The more "correct" way is to aggregate prior to doing the joins.
The second way is simpler, so I'll suggest COUNT(DISTINCT)
:
SELECT sc.id AS ID, sc.name AS Name,
COUNT(DISTINCT s.id) AS num_Students,
COUNT(DISTINCT c.id) AS num_Classes,
COUNT(DISTINCT g.id) AS num_Grades
FROM student s INNER JOIN
class c
ON s.classId = c.id INNER JOIN
grade g
ON c.gradeId = g.id INNER JOIN
school sc
ON g.sclId = s.id
GROUP BY sc.id, sc.name;
Notes:
name
as well as id
).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.