SQL:检索总和作为subselect非常慢

时间:2012-12-23 21:01:22

标签: mysql performance sum subquery

我正在尝试获取一些平均值和几行的总和,按一天中的每个小时进行分组。另外我想获取一个额外的列,其中我没有获得每小时的总和(在分组时获取),但是我想要获取所有行的总和,直到该特定日期。 SQL语句发布在下面。

我现在的问题是,在超过25k行的MySQL数据库上执行查询大约需要8秒(CPU i5 / 8GB RAM)。我发现子选择(... AS '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;

1 个答案:

答案 0 :(得分:0)

不是对所有这些字段进行分组,而是一个更简单(更快)的解决方案(来自here)可能是:

GROUP BY UNIX_TIMESTAMP(timestamp_local)/3600

我无法想象您的查询会返回您想要的结果(如果我正确理解您的要求)。我理解你的要求,因为当给定小时没有行时,你想要计算所有行的总和,小时&lt;那个小时。 MySQL不会选择空分组(对于子查询部分)。

在我所知道的MySQL中没有简单有效的方法可以做到这一点,我建议创建一个临时表,其中包含您所查看范围内的所有可能的分组值(可能带有循环)。您可以预先设置此表几年,并可能根据需要添加行。然后你可以离开加入这张桌子和你的桌子。

如果您使用的是MSSQL,那么您可能已经使用了递归CTE,尽管这可能非常慢。对于MySQL替代品,请查看this或google“mysql cte”。使用递归执行此操作的方法是(左)重复连接同一个表HOUR = HOUR+1,直到获得非NULL值,然后停止。对于其中的每一个,您将向后计算总和。