计算MySQL中的运行总计

时间:2009-03-20 01:36:10

标签: mysql sql

我有这个MySQL查询:

SELECT DAYOFYEAR(`date`)  AS d, COUNT(*) 
FROM  `orders` 
WHERE  `hasPaid` > 0
GROUP  BY d
ORDER  BY d

返回的内容如下:

d  | COUNT(*) |
20 |  5       |
21 |  7       |
22 | 12       |
23 |  4       |

我真正喜欢的是最后一列显示运行总数:

d  | COUNT(*) | ??? |
20 |  5       |   5 |
21 |  7       |  12 |
22 | 12       |  24 |
23 |  4       |  28 |

这可能吗?

8 个答案:

答案 0 :(得分:104)

也许是一个更简单的解决方案,可以防止数据库不得不进行大量查询。这只执行一个查询,然后在一次传递中对结果进行一些数学计算。

SET @runtot:=0;
SELECT
   q1.d,
   q1.c,
   (@runtot := @runtot + q1.c) AS rt
FROM
   (SELECT
       DAYOFYEAR(`date`) AS d,
       COUNT(*) AS c
    FROM  `orders`
    WHERE  `hasPaid` > 0
    GROUP  BY d
    ORDER  BY d) AS q1

这将为您提供额外的RT(运行总计)列。不要错过顶部的SET语句来初始化运行的总变量,否则您将获得一列NULL值。

答案 1 :(得分:10)

SELECT 
   DAYOFYEAR(O.`date`)  AS d, 
   COUNT(*),
   (select count(*) from `orders` 
       where  DAYOFYEAR(`date`) <= d and   `hasPaid` > 0)
FROM  
  `orders` as O
WHERE  
  O.`hasPaid` > 0
GROUP  BY d
ORDER  BY d

这将需要一些语法调整(我没有MySQL来测试它),但它向您展示了这个想法。子查询只需返回并添加已包含在外部查询中的所有新内容,并且必须为每一行执行此操作。

看看this question如何使用联接来完成同样的工作。

通过不断增长的数据解决性能下降的问题:因为有最大值。一年366天,我假设您没有多年运行此查询,子查询将被评估多达366次。使用适当的日期索引和hasPaid标志,你就可以了。

答案 2 :(得分:2)

Starting with MySQL 8, you will be using window functions for this kind of query:

SELECT dayofyear(`date`) AS d, count(*), sum(count(*)) OVER (ORDER BY dayofyear(`date`))
FROM `orders`
WHERE `hasPaid` > 0
GROUP BY d
ORDER BY d

In the above query, the aggregate function count(*) is nested inside of the window function sum(..) OVER (..), which is possible because of the logical order of operations in SQL. If that's too confusing, you can easily resort to using a derived table or a WITH clause to better structure your query:

WITH daily (d, c) AS (
  SELECT dayofyear(`date`) AS d, count(*)
  FROM `orders`
  WHERE `hasPaid` > 0
  GROUP BY d
)
SELECT d, c, sum(c) OVER (ORDER BY d)
ORDER BY d

答案 3 :(得分:1)

我会说这不可能每一行都应该是独立的。使用编程语言获取这些值

答案 4 :(得分:1)

除非您没有其他选择,只能在sql中执行此操作,否则我将使用编程语言对结果进行求和。随着桌子的增长,这样的嵌套将变得非常缓慢。

答案 5 :(得分:0)

你可以使用Cross Join语句或一些slef连接来破解它,但是对于任何大型数据集都会变慢,所以最好在后查询处理器中完成;客户端代码中的游标

答案 6 :(得分:0)

这是游标比基于集合的查询更快的地方之一,如果性能很关键,我会

  • 在MySql之外执行此操作 或
  • 使用MySql 5游标

答案 7 :(得分:0)

可以使用MySQL中的临时表来计算运行余额。以下查询应该起作用:

System.Data.SqlClient

临时表用于组织查询。请注意,只有在与MySQL服务器的连接期间存在一个临时表

上面的查询使用一个子查询,该查询返回临时表中直至当前行的所有行的余额。余额将分配给实际表中的当前行