Mysql SQL:检索作为子选择的总和非常慢

Mysql SQL:检索作为子选择的总和非常慢,mysql,performance,sum,subquery,Mysql,Performance,Sum,Subquery,我试图在几行上取一些平均值和一些总和,按一天中的每个小时分组。另外,我还想获取一个额外的列,在这个列中,我不获取分组时获取的每个小时的总和,而是获取在特定日期之前所有行的总和。SQL语句发布在下面 我现在的问题是,在一个超过25k行的MySQL数据库上执行查询大约需要8秒的CPU i5/8GB RAM。我确定子选择。。。因为“rain_sum”让它变得很慢。我现在的问题是:我的思维方式是否过于复杂?有没有更简单的方法来获得与我从下面的查询中得到的相同的结果 SELECT `timesta

我试图在几行上取一些平均值和一些总和,按一天中的每个小时分组。另外,我还想获取一个额外的列,在这个列中,我不获取分组时获取的每个小时的总和,而是获取在特定日期之前所有行的总和。SQL语句发布在下面

我现在的问题是,在一个超过25k行的MySQL数据库上执行查询大约需要8秒的CPU i5/8GB RAM。我确定子选择。。。因为“rain_sum”让它变得很慢。我现在的问题是:我的思维方式是否过于复杂?有没有更简单的方法来获得与我从下面的查询中得到的相同的结果

SELECT
    `timestamp_local` AS `date`,
    AVG(`one`) AS `one_avg`,
    AVG(`two`) AS `two_avg`,
    SUM(`three`) AS `three_sum`,
    (SELECT SUM(`b`.`three`)
        FROM `table` AS `b`
        WHERE `b`.`timestamp_local` <= SUBDATE(`a`.`timestamp_local`, INTERVAL -1 SECOND)
        LIMIT 0,1) AS `three_sum`
FROM  `table` AS  `a`
GROUP BY
    HOUR( `a`.`timestamp_local` ),
    DAY( `a`.`timestamp_local` ),
    MONTH( `a`.`timestamp_local` ),
    WEEK( `a`.`timestamp_local` ),
    YEAR( `a`.`timestamp_local` )
ORDER BY `a`.`timestamp_local` DESC
LIMIT 0, 24;

与其对所有这些字段进行分组,不如采用以下更简单、更快的解决方案:

如果我正确理解您的需求,我无法想象您的查询会返回您想要的结果。我理解您的要求,因为当给定的小时内没有行时,您希望计算所有行的总和,其中hour<该小时。MySQL不会为子查询部分选择空分组

据我所知,在MySQL中没有一种简单有效的方法可以做到这一点,我建议创建一个临时表,其中包含所有可能的分组值,这些值可能在您使用循环查看的范围内。您可以提前几年设置此表,并根据需要添加行。然后你可以左键连接这个表和你的表


如果您使用的是MSSQL,则可以使用递归CTE,尽管这可能会非常缓慢。查看或谷歌mysql cte,寻找mysql替代方案。使用递归实现这一点的方法是,在HOUR=HOUR+1的时间内,在同一个表上重复左键联接,直到得到一个非NULL值,然后停止。对于每一项,您将向后计算总和。

请显示创建表。主要是,你有一个关于时间戳_local的索引吗?是的,有一个关于时间戳_local的索引。“显示创建表”是什么意思?你想知道桌子的结构吗?不,你误解了。我想获取每个小时的分组总和数据库包含天气信息,我想获取每个小时的降雨量,我使用常规总和。但除了每小时的降雨量之外,我还想获取自数据库中填入天气信息以来的总降雨量,例如,上一小时的降雨量为5mm,自天气记录以来的总降雨量为550mm。但是通过timestamp/3600进行分组的提示非常棒,而且很有帮助。谢谢如果你想从一开始就获得总降雨量,除了这一小时的降雨量,而不是非此即彼的情况,我的大部分回答都是正确的。我的回答是基于假设每小时不下雨,如果有,这是一个简单的情况,加入表本身并不是特别快,但是,SQL不是真正为这种类型的操作而做的,但是在C++或PHP之类的东西中非常容易。也许中间的一步是创建一个每小时总和的表,这非常有趣,因为我有一个PHP算法,它可以累积降雨量。但是我想在SQL中实现它,因为我认为它会更高效、更快,并且在软件开发的理念中,在从DB中获取数据的同时聚合它更有意义,而不是获取数据然后在数据库上运行算法。因此,我想我将重复使用我的PHP方法。当然,您可以在SQL中使用一段时间和一个游标,执行与在PHP中完全相同的操作,执行一个查询以按小时排序的行,并在运行时计算值,但这可能仍然较慢或非常接近PHP的速度,这就是高级SQL和基本PHP的区别。我称赞你的timestamp/3600太快了。当我第一次尝试它时,我只是看着sql执行时间快速下降,但没有提到它没有给我正确的结果。现在,每一行包含来自每个db行的常规时间戳,但不包含分组平均结果。因此,当每30秒将一行写入数据库,并且我尝试获取最后24小时时,我得到24行,具有规则的时间戳30秒间隔,一个平均值始终相同。因此,以这种方式分组既不起作用也没有帮助。
GROUP BY UNIX_TIMESTAMP(timestamp_local)/3600