2017-08-21 51 views
1

問題:當每張表的行數很少(比如少於一千個)時,我的查詢完美無缺。 但是,當我試圖用虛擬數據填充數據庫時,頁面無休止地加載。MYSQL - 如何優化3 LEFT連接表?

我使用3臺加入:

  1. 學生 - 它持有的學生基本信息(7,000+行)

    索引列:student_id數據性別

  2. 曠工 - 這對於缺席的記錄(行31,000)

    索引列:absent_idstudent_id數據原諒

  3. 遲到 - 這對於遲到的記錄( 19,000+行)

    索引列:tardi_id,student_i d原諒

輸出表看起來是這樣的:

Name  | Grade | Section | Sex | Age | Tardiness Count | Absence Count 
____________________________________________________________________ 
John Smith | 7  | E05-A | Male| 18 | 6    | 5 

這是我查詢:

SELECT students.student_id , students.name_l, students.name_f, students.name_m, students.grade, students.section, students.age_s, students.sex, 

(SELECT COUNT(distinct absenteeism.absent_id) FROM absenteeism 
WHERE absenteeism.excused=0 AND absenteeism.student_id = students.student_id) AS absents, 

(SELECT COUNT(distinct tardiness.tardi_id) FROM tardiness 
WHERE tardiness.excused=0 AND tardiness.student_id = students.student_id) AS tardi 

FROM students 
LEFT JOIN absenteeism ON absenteeism.student_id = students.student_id 
LEFT JOIN tardiness ON tardiness.student_id = students.student_id 
GROUP BY students.student_id 
ORDER BY name_l ASC LIMIT 0, 15 

我查詢簡單地獲取所有數據那我需要從學生桌面顯示然後計算缺勤率遲到的所有記錄對於每一行都沒有標記爲相應的student_id

這裏是擴大解釋查詢的

id select_type   table  type possible_keys  key   key_len ref       rows filtered extra 

1 PRIMARY    students index NULL    PRIMARY  34  NULL      6900 100.00  Using temporary; Using filesort 
1 PRIMARY    absenteeism ref  student_id   student_id 34  lnhs.students.student_id 1583 100.00  Using index 
1 PRIMARY    tardiness ref  student_id   student_id 34  lnhs.students.student_id 3851 100.00  Using index 
3 DEPENDENT SUBQUERY tardiness ref  student_id,excused student_id 34  func      3851 100.00  Using where 
2 DEPENDENT SUBQUERY absenteeism ref  student_id,excused student_id 34  func      1583 100.00  Using where 

回答

1

什麼是可能殺死你出現在您的SELECT子句中的兩個相關的聚集查詢。相反,請在單獨的真實子查詢中進行聚合,然後將它們加入到您的students表中。

SELECT 
    s.*,  -- replace with whatever columns you actually want 
    COALESCE(t1.num_absent, 0) AS num_absent, 
    COALESCE(t2.num_tardy, 0) AS num_tardy 
FROM students s 
LEFT JOIN 
(
    SELECT student_id, COUNT(DISTINCT absent_id) AS num_absent 
    FROM absenteeism 
    WHERE excused = 0 
    GROUP BY student_id 
) t1 
    ON s.student_id = t1.student_id 
LEFT JOIN 
(
    SELECT student_id, COUNT(DISTINCT tardi_id) AS num_tardy 
    FROM tardiness 
    WHERE excused = 0 
    GROUP BY student_id 
) t2 
    ON s.student_id = t2.student_id 
ORDER BY 
    s.name_l 
LIMIT 0, 15 

請注意,我使用COALESCE()在每個學生的缺席和遲到計數。之所以這樣做,以及爲什麼(明智地)使用LEFT JOIN的原因是可能是某個學生既不在場也不遲到。 INNER JOIN會將該學生從結果集中移除。相反,COALESCE允許檢測到學生沒有出現在缺席或晚期子查詢中,在這些情況下,我們可以爲相應數字報告零。

+1

謝謝!該頁面現在立即加載!您的解決方案比我的速度快100倍。男人,我真的應該在MYSQL中學習更多。我很確定這也將在未來幫助我。謝謝 – legitghost