MYSQL查询需要永远

时间:2015-10-29 02:35:46

标签: mysql

我的报告需要运行才能满足政府机构的报告要求。该报告应该在给定的时间段内返回每个模块中每个学生的学习负荷。

例如,报告需要在特定年份和学期内返回给定模块中注册的学生,并按人口普查日期(政府指定日期,之后学生负责该单位的费用)即使他们退出了)

所以我写了这个mysql查询

 SELECT 
   e.enrolstudent AS '313', 
   (SELECT c.ntiscode FROM course c WHERE c.courseid=ec.courseid)  AS '307', 
   e.startdate as '534',
   'AOU' as '333',
   m.mod_eftsl as '339',
   e.enrolmod as '354',
   e.census_date as '489',
   m.diciplinecode as '464',
   (CASE 
      WHEN m.mode = 'Face to Face' THEN 1
      WHEN m.mode = 'Online' THEN 2 
      WHEN m.mode = 'RPL' THEN 5 
      ELSE 3      
   END) AS '329',
   'A6090' as '477',
   up.citizen AS '358',
   vf.maxcontribute as '392',
   vf.studentstatus as '490',
   vf.total_amount_charged as '384',
   vf.amount_paid as '381',
   vf.loan_fee as '529',
   u.chessn as '488',
   m.workexp as '337',
   '0' as '390',
   m.sumwinschool as '551',
   vf.help_debt as '558'
FROM 
   enrolment e
   INNER JOIN enrolcourse AS ec ON ec.studentid=e.enrolstudent
   INNER JOIN vetfee AS  vf ON vf.userid=e.enrolstudent
   INNER JOIN users AS  u ON u.userid = e.enrolstudent
   INNER JOIN users_personal AS  up ON up.userid = e.enrolstudent
   INNER JOIN module AS m ON m.modshortname = e.enrolmod
WHERE 
      e.online_intake in (select oi.intakecode from online_intake oi where STR_TO_DATE(oi.censusdate,'%d-%m-%Y') > '2015-07-01' and STR_TO_DATE(oi.censusdate,'%d-%m-%Y') < '2015-09-31') AND 
      e.enrolstudent NOT LIKE '%onlinetutor%' AND 
      e.enrolstudent NOT LIKE '%tes%' AND 
      e.enrolstudent NOT like '%student%' AND 
      e.enrolrole = 'student' 
ORDER BY e.enrolstudent;"

似乎挂了,我让它运行了一个小时而没有结果。登记表中只有10189条记录,登记册中有1538条记录,模块中有650条记录。我不认为它的记录数量,我猜我刚刚构建了我的查询错误,第一次使用连接(除了自然)。任何提高这一点的想法或提示都将不胜感激。

select count(*) from enrolment;
+----------+
| count(*) |
+----------+
|    10189 |
+----------+

select count(*) from enrolcourse;
+----------+
| count(*) |
+----------+
|     1538 |
+----------+

select count(*) from vetfee;
+----------+
| count(*) |
+----------+
|     1538 |
+----------+

select count(*) from users;
+----------+
| count(*) |
+----------+
|     1249 |
+----------+

select count(*) from users_personal;
+----------+
| count(*) |
+----------+
|      941 |
+----------+

select count(*) from module;
+----------+
| count(*) |
+----------+
|      650 |

以下是EXPLAIN的结果

+----+--------------------+-------+------+---------------+------+---------+------+-------+---------------------------------+
| id | select_type        | table | type | possible_keys | key  | key_len | ref  | rows  | Extra                           |
+----+--------------------+-------+------+---------------+------+---------+------+-------+---------------------------------+
|  1 | PRIMARY            | m     | ALL  | NULL          | NULL | NULL    | NULL |   691 | Using temporary; Using filesort |
|  1 | PRIMARY            | up    | ALL  | NULL          | NULL | NULL    | NULL |   987 | Using join buffer               |
|  1 | PRIMARY            | u     | ALL  | NULL          | NULL | NULL    | NULL |  1180 | Using where; Using join buffer  |
|  1 | PRIMARY            | ec    | ALL  | NULL          | NULL | NULL    | NULL |  1607 | Using where; Using join buffer  |
|  1 | PRIMARY            | e     | ALL  | NULL          | NULL | NULL    | NULL | 10629 | Using where; Using join buffer  |
|  1 | PRIMARY            | vf    | ALL  | NULL          | NULL | NULL    | NULL | 10959 | Using where; Using join buffer  |
|  3 | DEPENDENT SUBQUERY | oi    | ALL  | NULL          | NULL | NULL    | NULL |    42 | Using where                     |
|  2 | DEPENDENT SUBQUERY | c     | ALL  | NULL          | NULL | NULL    | NULL |    23 | Using where                     |
+----+--------------------+-------+------+---------------+------+---------+------+-------+---------------------------------+

1 个答案:

答案 0 :(得分:1)

摆脱那些相关的子查询。改为使用连接。

另外,使用BETWEEN减少一次STR_TO_DATE电话

最后,您应该考虑一种消除所有LIKE次呼叫的方式。

SELECT 
    e.enrolstudent AS '313', 
    c.ntiscode AS '307', 
    e.startdate as '534',
   'AOU' as '333',
    m.mod_eftsl as '339',
    e.enrolmod as '354',
    e.census_date as '489',
    m.diciplinecode as '464',
    (CASE 
         WHEN m.mode = 'Face to Face' THEN 1
         WHEN m.mode = 'Online' THEN 2 
         WHEN m.mode = 'RPL' THEN 5 
         ELSE 3      
    END) AS '329',
   'A6090' as '477',
    up.citizen AS '358',
    vf.maxcontribute as '392',
    vf.studentstatus as '490',
    vf.total_amount_charged as '384',
    vf.amount_paid as '381',
    vf.loan_fee as '529',
    u.chessn as '488',
    m.workexp as '337',
    '0' as '390',
    m.sumwinschool as '551',
    vf.help_debt as '558'
FROM 
    enrolment e
    INNER JOIN enrolcourse AS ec ON ec.studentid=e.enrolstudent
    INNER JOIN course AS c ON c.courseid = ec.courseid
    INNER JOIN vetfee AS  vf ON vf.userid=e.enrolstudent
    INNER JOIN users AS  u ON u.userid = e.enrolstudent
    INNER JOIN users_personal AS  up ON up.userid = e.enrolstudent
    INNER JOIN module AS m ON m.modshortname = e.enrolmod
    INNER JOIN online_intake oi ON oi.intakecode = e.online_intake
        AND STR_TO_DATE(oi.censusdate, '%d-%m-%Y') BETWEEN '2015-07-01' AND '2015-09-31'
WHERE e.enrolstudent NOT LIKE '%onlinetutor%'
    AND e.enrolstudent NOT LIKE '%tes%' 
    AND e.enrolstudent NOT like '%student%'
    AND e.enrolrole = 'student' 
ORDER BY e.enrolstudent;

根据您发布的EXPLAIN输出,您还需要添加以下索引:

ALTER TABLE enrolment
    ADD INDEX (enrolstudent),
    ADD INDEX (enrolmod),
    ADD INDEX (online_intake);
ALTER TABLE enrolcourse
    ADD INDEX (studentid),
    ADD INDEX (courseid);
ALTER TABLE course
    ADD INDEX (courseid);
ALTER TABLE vetfee
    ADD INDEX (userid);
ALTER TABLE users
    ADD INDEX (userid);
ALTER TABLE users_personal
    ADD INDEX (userid);
ALTER TABLE module
    ADD INDEX (modshortname);
ALTER TABLE online_intake
    ADD INDEX (intakecode);