简体   繁体   中英

Get count of data of multiple table using join

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:

  • Parentheses are not needed for joins in "real" SQL databases.
  • You should be aggregating by all non-aggregated columns (that includes name as well as id ).
  • Table aliases are strongly recommended.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM