MYSQL-如何优化3个左连接表?
问题:当每个表的行数很少(比如少于1000行)时,我的查询工作得非常好但是当我试图用虚拟数据填充数据库时,页面会无休止地加载。 我使用3个表来连接:MYSQL-如何优化3个左连接表?,mysql,database,join,indexing,Mysql,Database,Join,Indexing,问题:当每个表的行数很少(比如少于1000行)时,我的查询工作得非常好但是当我试图用虚拟数据填充数据库时,页面会无休止地加载。 我使用3个表来连接: 学生-保存学生的基本信息(7000多行) 索引列:学生id、年级和性别 旷工-这保存了旷工记录(31000多行) 索引列:缺席id,学生id,免责 拖期-保存拖期记录(19000多行) 索引列:tardi\u id,学生id,免责 输出表如下所示: Name | Grade | Section | Sex | Age | Tard
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
我的查询只是从学生表中获取了我需要显示的所有数据,然后统计旷工和迟到表中的所有记录,这些记录没有为每一行标记相应的学生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
最可能让您丧命的是出现在
SELECT
子句中的两个相关聚合查询。相反,在单独的真正子查询中进行聚合,然后将它们连接到学生表中
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()
。这样做的原因,以及(明智地)使用左连接的原因是,给定的学生既不缺席也不迟到。内部联接将从结果集中删除该学生。相反,COALESCE
允许检测学生没有出现在缺席或迟到的子查询中,在这些情况下,我们可以为相应的数字报告零。谢谢!页面现在立即加载!你的解决方案比我的快100倍。老兄,我真的应该多学习MYSQL。我很确定这对我将来也有帮助。谢谢