【问题标题】:subselect alternatives子选择替代品
【发布时间】:2013-01-31 00:27:16
【问题描述】:

请看一下这个查询:

SELECT
    (SELECT COUNT(id) FROM result WHERE `mterm1` > r.mterm1 AND lesson_id = r.lesson_id) + 1 AS `pos_mt1_school`,
    (SELECT COUNT(id) FROM result WHERE `mterm1` > r.mterm1 AND lesson_id = r.lesson_id AND class_id = r.class_id) + 1 AS `pos_mt1_class`,

    (SELECT COUNT(id) FROM result WHERE `term1` > r.term1 AND lesson_id = r.lesson_id) + 1 AS `pos_t1_school`,
    (SELECT COUNT(id) FROM result WHERE `term1` > r.term1 AND lesson_id = r.lesson_id AND class_id = r.class_id) + 1 AS `pos_t1_class`,

    (SELECT COUNT(id) FROM result WHERE `mterm2` > r.mterm2 AND lesson_id = r.lesson_id) + 1 AS `pos_mt2_school`,
    (SELECT COUNT(id) FROM result WHERE `mterm2` > r.mterm2 AND lesson_id = r.lesson_id AND class_id = r.class_id) + 1 AS `pos_mt2_class`,

    (SELECT COUNT(id) FROM result WHERE `term2` > r.term2 AND lesson_id = r.lesson_id) + 1 AS `pos_t2_school`,
    (SELECT COUNT(id) FROM result WHERE `term2` > r.term2 AND lesson_id = r.lesson_id AND class_id = r.class_id) + 1 AS `pos_t2_class`,

    r.*, student.* FROM result r

LEFT JOIN lessons lesson ON r.lesson_id = lesson.id
LEFT JOIN students student ON r.student_id = student.id
LEFT JOIN classes class ON student.class_id = class.id

WHERE student.id = 217 ORDER BY lesson.id ASC

我想显示学生的考试成绩。因此,首先从表result 中选择他的成绩(考试成绩),然后加入lessons 以显示课程名称,最后计算学生在他所在班级和学校的每节课中的位置。 (根据他的考试成绩)

该查询运行良好,但执行大约需要 2 秒。 (性能问题)

该查询是否有任何优化? (以及它的子选择查询的替代方法)

【问题讨论】:

    标签: mysql performance subquery


    【解决方案1】:

    您正在子选择中进行累积计数。

    我无法轻易想到在 MySQL 中通过单个查询执行此操作的另一种方法。如果“=”中的“>”,则可以将其转换为连接。但在这种情况下这是不可能的。

    您可以使用如下查询将其转换为带有聚合的显式交叉联接:

    SELECT sum(case when r2.mterm1  > r.mterm1 then 1 else 0 end)+1 as `pos_mt1_school`,
           sum(case when r2.mterm1 > r.mterm1 and r2.class_id = r.class_id) + 1 then 1 else 0 end) AS `pos_mt1_class`,
           . . .
        r.*, student.*
    FROM result r LEFT JOIN
         lessons lesson
         ON r.lesson_id = lesson.id LEFT JOIN
         students student
         ON r.student_id = student.id LEFT JOIN
         classes class
         ON student.class_id = class.id join
         result r2
         on r.lesson_id = r2.lesson_id
    WHERE student.id = 217
    group by r.result_id
    ORDER BY lesson.id ASC
    

    我不确定这会比原始版本快。顺便说一句,原始版本将通过添加两个索引来加快速度:result(lesson_id, term2) 和 result(less_id, class_id, term2)。

    【讨论】:

    • 感谢 Gordon,您的查询在 0.0517 秒内执行。比原来的查询好多了。 (mysql说你的查询有一些语法错误。在第2行,你忘记了then 1 else 0 end,而在最后一次连接中,on被忘记了)
    猜你喜欢
    • 2010-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-02
    • 1970-01-01
    • 2019-06-07
    相关资源
    最近更新 更多