如何优化以下查询:-
SELECT
YEAR(msa.DATE) AS Year,
MONTH(msa.DATE) AS Month,
SUM(msk.POINT) AS Ps,
SUM(msa.VIDEO_SCORE) AS Video,
SUM(msa.EXERCISESCORE) AS Lessons,
SUM(msa.DS) AS DS
FROM student_p msk
RIGHT JOIN student_act msa ON msk.DATE = msa.DATE
GROUP BY YEAR(msa.DATE), MONTH(msa.DATE)
student_p表:-
student_act表:-
预期结果:-
4条答案
按热度按时间tktrz96b1#
在第二个查询中,您将按年份限制结果集。如果这是您想要做的,则应该基于日期执行,而不是基于日期的函数,因为它是non-sargable。这样就可以使用Hossam建议的索引。(过于)简单地说,
HAVING
子句是在完成所有工作之后应用的,而WHERE
子句减少了正在完成的工作量:MAKEDATE(年,一年中的某一天)
返回一个日期,给定年份和年中的日期值。dayofyear必须大于0,否则结果为NULL。
在你的一条评论中,你说你想要一个
full join
,MySQL没有,但是你可以用一个(LEFT|RIGHT) JOIN
UNION
和另一个(LEFT|RIGHT) JOIN
实现同样的目标。输出:
| 年份|月份|Ps|视频|教训|DS|
| - ------|- ------|- ------|- ------|- ------|- ------|
| 二○二三|十一|四十五|二十二点四十三|二三三点四四五五|二十三|
| 二○二三|十个|零|二十四点五六六|二百三十二|三十四|
| 小行星2022|十个|零|四十六|六十八|六十六|
| 二〇一三年|十个|六十五|零|零|零|
两个CTE进行聚合。我保留了
WHERE
子句,但注解掉了。UNION
中的第一个查询是当前的RIGHT JOIN
,它从右侧表中检索所有记录,无论它们在左手表中是否有关联行。第二个查询然后从左侧表中获取所有在右侧没有关联行的行。下面是一个db<>fiddle,其中调整了无效日期和重复PK值。
这是你要找的吗?
kwvwclae2#
对于初学者,您可以尝试index student_act表上的DATE字段。索引有助于SQL引擎更快地找到基于该字段的记录。
我的SQL:
索引优化了SQL引擎中的查找过程,如果查询匹配基于MULTIPLE字段的记录,或者像您的示例中一样,匹配的字段是非数字的,则通常非常有效。
另外,尝试将字段重命名为不同于DATE的名称,因为它在某些SQL引擎中是保留字。
9fkzdhlc3#
你也可以试试这个
ygya80vv4#
不要使用YEAR()和MONTH()函数,尝试按LAST_DAY()分组。它会给出包含任何DATE、DATETIME或TIMESTAMP的月份的最后一天。
就像这样:
在
student_p(date, POINT)
和student_act(DATE, VIDEO_SCORE, EXERCISES_SCORE, DS)
上分别创建一个覆盖索引。这种形式的查询和那些索引将有很大的帮助。