在MySQL中计算运行总数

cxfofazt  于 2023-10-15  发布在  Mysql
关注(0)|答案(5)|浏览(127)

我有这个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 |

这可能吗?

7rtdyuoh

7rtdyuoh1#

MySQL警告:在表达式中设置用户变量已被弃用,并将在未来版本中删除。
也许是一个更简单的解决方案,可以防止数据库进行大量的查询。这只执行一个查询,然后在一次传递中对结果进行一些数学运算。

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语句,首先初始化运行的total变量,否则您将只得到一列NULL值。

xkftehaa

xkftehaa2#

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标志的适当索引,你会没事的。

k4emjkb1

k4emjkb13#

从MySQL 8开始,你将使用window functions来进行这种查询:

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

在上面的查询中,聚合函数count(*)嵌套在窗口函数sum(..) OVER (..)内部,这是可能的,因为logical order of operations in SQL。如果这太令人困惑,你可以很容易地使用派生表或WITH clause来更好地构造你的查询:

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
s1ag04yj

s1ag04yj4#

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

CREATE TEMPORARY table orders_temp1 (SELECT id, DAYOFYEAR(`date`)  AS d, COUNT(*) as total FROM  `orders` WHERE  `hasPaid` > 0 GROUP BY d ORDER  BY d);
CREATE TEMPORARY table orders_temp2 (SELECT * FROM orders_temp1);
SELECT d, total, (SELECT SUM(t2.total) FROM orders_temp2 t2 WHERE t2.id<=t1.id) as running_total FROM orders_temp1 t1;

临时表用于组织查询。请注意,临时表仅在连接到MySQL服务器期间存在
上面的查询使用了一个子查询,它返回临时表中所有行的余额,包括当前行。将余额分配给实际表中的当前行

6za6bjd0

6za6bjd05#

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

相关问题