MYSQL使用左连接加入3个表

时间:2014-01-15 18:44:23

标签: php mysql sql join left-join

我有这些表格:

pupils: (id_pupil, name, surname, email, user, pass, level, class)
incidents: (id_incidents, date, time, type_incident, comments, id_pupil, id_user, subject, id_trimester)
qualifications: (id_qualification, qualification, date, time, subject, id_pupil, id_user, id_trimester, type_qualification)

我做了这个查询:

SELECT 
    pupils.id_pupil
  , name
  , surname
  , round(avg(qualifications.calificacion),2) as average
  , count(qualifications.calificacion) as count
  , COALESCE(sum(type_incident='miss' and level=1 and class='A' and id_trimester=1),0) as misses
  , COALESCE(sum(type_incident='delay' and level=1 and class='A' and id_trimester=1),0) as delays
  , COALESCE(sum(type_incident='attitude' and level=1 and class='A' and id_trimester=1),0) as attitude
  , COALESCE(sum(type_incident='miss_justif' and level=1 and class='A' and id_trimester=1),0) as misses_justificadas 
FROM 
    pupils 
    left join incidents         ON incidents.id_pupil=pupils.id_pupil
    left join qualifications    ON qualifications.id_pupil=pupils.id_pupil
WHERE 
    level=1
    and class='A' 
    and id_trimester=1 
    and type_qualification='class' 
    and qualifications.id_trimester=incidents.id_trimester
GROUP BY id_pupil

但问题是,我必须得到的正确结果是:

enter image description here

我得到了:

enter image description here

问题在于,增加了班级资格和未命中数(17x6(2个未命中,1个延迟,1个态度和2个misses_just)= 102))并且我不希望这样。我想在第一张图片中显示正确的信息。

你想帮助我吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

问题是您正在创建的关系会复制大量行。

我个人的做法是:

  1. 首先从incidents
  2. 获取所需的数据
  3. 将“子查询”加入到学生和资格所需的数据
  4. 这样的事情:

    select 
        p.id_pupil, p.name, p.surname, 
        (case
            when type_incident = 'miss' and level = 1 and class='A' then incident_count 
            else 0
        end) as misses,
        (case
            when type_incident = 'delay' and level = 1 and class='A' then incident_count 
            else 0
        end) as delays,
        (case
            when type_incident = 'attitude' and level = 1 and class='A' then incident_count 
            else 0
        end) as attitude,
        (case
            when type_incident = 'miss_justif' and level = 1 and class='A' then incident_count 
            else 0
        end) as miss_justif
    from 
        pupils as p
        left join (
            select id_pupil, class, id_trimester, type_qualification, avg(qualification) as q_avg
            from qualifications
            group by id_pupil, class, id_trimester, type_qualification
        ) as q on p.id_pupil = q.id_pupil
        left join (
            select id_pupil, class, type_incident, level, class, count(id_incidents) as incident_count
            from incidents
            group by id_pupil, id_trimester, incident, level, class
        ) as i on p.id_pupil = i.id_pupil
    where ...