Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MYSQL-如何优化3个左连接表?_Mysql_Database_Join_Indexing - Fatal编程技术网

MYSQL-如何优化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

问题:当每个表的行数很少(比如少于1000行)时,我的查询工作得非常好但是当我试图用虚拟数据填充数据库时,页面会无休止地加载。

我使用3个表来连接:

  • 学生-保存学生的基本信息(7000多行)

    索引列:学生id年级性别

  • 旷工-这保存了旷工记录(31000多行)

    索引列:缺席id学生id免责

  • 拖期-保存拖期记录(19000多行)

    索引列:tardi\u id学生id免责

  • 输出表如下所示:

    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。我很确定这对我将来也有帮助。谢谢