如何优化这个IF-MySQL查询

如何优化这个IF-MySQL查询,mysql,optimization,Mysql,Optimization,此MySQL查询运行时间超过6分钟。瓶颈是生成“活动完成”列的最后一块。我之所以将其编写为子查询,是因为如果itemtype=“course”,我需要查找每个类中每个用户的所有其他项类型的最大日期,而不是整个表列的最大日期。我肯定有更好的办法,但我不知道是什么。有人能帮我吗 SELECT DISTINCT u.firstname AS 'First' , u.lastname AS 'Last', c.fullname AS 'Course', IF (gi.itemtype = '

此MySQL查询运行时间超过6分钟。瓶颈是生成“活动完成”列的最后一块。我之所以将其编写为子查询,是因为如果itemtype=“course”,我需要查找每个类中每个用户的所有其他项类型的最大日期,而不是整个表列的最大日期。我肯定有更好的办法,但我不知道是什么。有人能帮我吗

SELECT DISTINCT 
  u.firstname AS 'First' , u.lastname AS 'Last', c.fullname AS 'Course', 
  IF (gi.itemtype = 'course', 
        CONCAT(c.fullname,"  COURSE TOTAL"), 
        gi.itemname) AS 'Item Name',

IFNULL(CONCAT(ROUND(gg.finalgrade,2),'/',ROUND(gi.grademax,2)), '0') 
  AS 'Points Earned',

IFNULL(CONCAT(ROUND((gg.finalgrade/gi.grademax),2)*100,'%'), '0%')
  AS 'Percentage',

(SELECT 
  IF(`Percentage`>=90, 'A', 
    IF(`Percentage`<90 AND `Percentage`>=80, 'B',
      IF(`Percentage`<80 AND `Percentage`>=70, 'C', 
        IF(`Percentage`<70 AND `Percentage`>=60, 'D', 'F'))))) 
  AS 'Grade',

IF(gi.itemtype = 'course',
  (SELECT 
     FROM_UNIXTIME(GREATEST(MAX(gg.timemodified), MAX(gg.timecreated)), 
                   '%m/%d/%Y')
   FROM mdl_course c
     JOIN mdl_grade_items gi
     JOIN mdl_grade_grades gg
   WHERE gg.userid=u.id 
     AND gi.courseid=c.id), 

   CASE 
     WHEN gg.timecreated IS NULL AND gg.timemodified IS NULL THEN '-'
     WHEN gg.timecreated IS NULL AND gg.timemodified IS NOT NULL THEN FROM_UNIXTIME(gg.timemodified, '%m/%d/%Y')
     WHEN gg.timecreated IS NOT NULL AND gg.timemodified IS NULL THEN FROM_UNIXTIME(gg.timecreated, '%m/%d/%Y')
     WHEN gg.timecreated<=gg.timemodified THEN FROM_UNIXTIME(gg.timemodified,'%m/%d/%Y')
   END)
  AS 'Activity Completed'

FROM mdl_user u
  JOIN mdl_user_enrolments ue on ue.userid=u.id
  JOIN mdl_enrol e ON e.id=ue.enrolid
  JOIN mdl_course c on c.id = e.courseid
  JOIN mdl_context AS ctx ON ctx.instanceid = c.id
  JOIN mdl_role_assignments AS ra ON ra.contextid = ctx.id
  JOIN mdl_role AS r ON r.id = e.roleid
  JOIN mdl_grade_items AS gi ON gi.courseid=c.id
  LEFT JOIN mdl_grade_grades AS gg ON gg.userid=u.id
    AND gg.itemid=gi.id

WHERE ue.status='0'
  AND gi.hidden = '0'
  AND gi.itemtype <> 'category'
  AND gg.excluded = '0'
  OR gg.excluded IS NULL

ORDER BY u.lastname, c.fullname, gi.itemtype DESC, gi.sortorder ASC
这就是我在向查询解释之前得到的结果。 我无法复制列标题。它们是:

id, select_type, table, type, possible_keys, key, key_len, ref, rows, extra

1   PRIMARY u   ALL PRIMARY             449 Using temporary; Using filesort
1   PRIMARY ue  ref mdl_userenro_enruse_uix,mdl_userenro_enr_ix,mdl_userenro_use_ix mdl_userenro_use_ix 8   skol_dev.u.id   1   Using where
1   PRIMARY e   eq_ref  PRIMARY,mdl_enro_cou_ix PRIMARY 8   skol_dev.ue.enrolid 1   
1   PRIMARY r   eq_ref  PRIMARY PRIMARY 8   skol_dev.e.roleid   1   Using index
1   PRIMARY c   eq_ref  PRIMARY PRIMARY 8   skol_dev.e.courseid 1   
1   PRIMARY ctx ref PRIMARY,mdl_cont_ins_ix mdl_cont_ins_ix 8   skol_dev.c.id   1   Using where; Using index
1   PRIMARY gi  ref mdl_graditem_itenee_ix,mdl_graditem_cou_ix  mdl_graditem_cou_ix 9   skol_dev.e.courseid 7   Using where
1   PRIMARY ra  ref mdl_roleassi_con_ix mdl_roleassi_con_ix 8   skol_dev.ctx.id 4   Using index
1   PRIMARY gg  eq_ref  mdl_gradgrad_useite_uix,mdl_gradgrad_ite_ix,mdl_gradgrad_use_ix mdl_gradgrad_useite_uix 16  skol_dev.u.id,skol_dev.gi.id    1   Using where
3   DEPENDENT SUBQUERY  gg  ref mdl_gradgrad_useite_uix,mdl_gradgrad_use_ix mdl_gradgrad_use_ix 8   skol_dev.u.id   6   
3   DEPENDENT SUBQUERY  c   index   PRIMARY mdl_cour_cat_ix 8       124 Using index; Using join buffer
3   DEPENDENT SUBQUERY  gi  ref mdl_graditem_cou_ix mdl_graditem_cou_ix 9   skol_dev.c.id   7   Using where; Using index

EXPLAIN
预先添加到完整查询中(即
EXPLAIN-SELECT…
),将其交给MySQL引擎,并将结果编辑到您的问题中。如果不知道查询优化器正在对查询执行什么操作,就不可能提供结论性的答案。如果没有直接的答案,我认为您需要在(gg.excluded='0'或gg.excluded为NULL)周围使用paren。否则,一旦一个条目具有gg,您的所有ue和gi条件都将被忽略。excluded为NULL。此外,除了加入之外,您对CTX、RA和R表不做任何操作。您可能会从查询中完全删除这些内容。。。如果有人报名参加某个课程,谁会在乎“角色分配”是谁呢。谢谢,亚伦,我已经在我的问题中添加了解释部分。谢谢,德拉普指出了失踪的帕伦夫妇。额外的表包括在内,因为我将添加更多的WHERE语句,以便报告中只包括学生。查看解释结果,我意识到我没有指明要在哪些字段上加入子查询表,所以我修复了这个问题。然后我改变了加入子查询表的顺序,现在我只剩下9秒了。我可以接受。:-)谢谢你的解释建议!
id, select_type, table, type, possible_keys, key, key_len, ref, rows, extra

1   PRIMARY u   ALL PRIMARY             449 Using temporary; Using filesort
1   PRIMARY ue  ref mdl_userenro_enruse_uix,mdl_userenro_enr_ix,mdl_userenro_use_ix mdl_userenro_use_ix 8   skol_dev.u.id   1   Using where
1   PRIMARY e   eq_ref  PRIMARY,mdl_enro_cou_ix PRIMARY 8   skol_dev.ue.enrolid 1   
1   PRIMARY r   eq_ref  PRIMARY PRIMARY 8   skol_dev.e.roleid   1   Using index
1   PRIMARY c   eq_ref  PRIMARY PRIMARY 8   skol_dev.e.courseid 1   
1   PRIMARY ctx ref PRIMARY,mdl_cont_ins_ix mdl_cont_ins_ix 8   skol_dev.c.id   1   Using where; Using index
1   PRIMARY gi  ref mdl_graditem_itenee_ix,mdl_graditem_cou_ix  mdl_graditem_cou_ix 9   skol_dev.e.courseid 7   Using where
1   PRIMARY ra  ref mdl_roleassi_con_ix mdl_roleassi_con_ix 8   skol_dev.ctx.id 4   Using index
1   PRIMARY gg  eq_ref  mdl_gradgrad_useite_uix,mdl_gradgrad_ite_ix,mdl_gradgrad_use_ix mdl_gradgrad_useite_uix 16  skol_dev.u.id,skol_dev.gi.id    1   Using where
3   DEPENDENT SUBQUERY  gg  ref mdl_gradgrad_useite_uix,mdl_gradgrad_use_ix mdl_gradgrad_use_ix 8   skol_dev.u.id   6   
3   DEPENDENT SUBQUERY  c   index   PRIMARY mdl_cour_cat_ix 8       124 Using index; Using join buffer
3   DEPENDENT SUBQUERY  gi  ref mdl_graditem_cou_ix mdl_graditem_cou_ix 9   skol_dev.c.id   7   Using where; Using index