Mysql SQL-有没有办法计算一系列日期的运行总数?

Mysql SQL-有没有办法计算一系列日期的运行总数?,mysql,join,cumulative-sum,Mysql,Join,Cumulative Sum,给定一个日期为1的事件列表,其中1表示某个事件,例如学生加入了一个组,-1表示某个事件离开了一个组,是否可以在SQL中按日期计算组大小?我有一个代码,可以生成一个范围内的所有日期。。。当我自己运行它时,它就工作了。然后我想按班级参加报名活动,并在每个日期登记总人数+1==类添加,-1==类删除 我想我缺少了SQL中连接和分组的基本原理 样本数据: CREATE TABLE classes(`id` int, `name` varchar(7)); INSERT INTO classes(`id`

给定一个日期为1的事件列表,其中1表示某个事件,例如学生加入了一个组,-1表示某个事件离开了一个组,是否可以在SQL中按日期计算组大小?我有一个代码,可以生成一个范围内的所有日期。。。当我自己运行它时,它就工作了。然后我想按班级参加报名活动,并在每个日期登记总人数+1==类添加,-1==类删除

我想我缺少了SQL中连接和分组的基本原理

样本数据:

CREATE TABLE classes(`id` int, `name` varchar(7));
INSERT INTO classes(`id`, `name`) VALUES
    (1, 'math'),
    (2, 'english'),
    (3, 'sciene');

CREATE TABLE enrollment_changes(
  `class_id` int, 
  `change_date` date, 
  `change` int);
INSERT INTO enrollment_changes
    (`class_id`, `change_date`, `change`)
VALUES
    (1, '2019-01-01', 1),
    (1, '2019-01-01', 1),
    (1, '2019-01-02', -1),
    (3, '2019-01-02', 1),
    (1, '2019-01-03', 1),
    (2, '2019-01-03', -1)
;
预期结果:

event_date   name      NetEnrollment
------------------------------------
2019-01-01   math      1
2019-01-01   english   0
2019-01-01   science   0
2019-01-02   math      1
2019-01-02   english   1
2019-01-02   science   0
2019-01-03   math      2
2019-01-03   english   1
2019-01-03   science   1

您可以使用以下解决方案:

SELECT date_range.event_date, c.name, IFNULL(SUM(e.change), 0) AS 'NetEnrollment'
FROM (
  SELECT adddate('1970-01-01',t4*10000 + t3*1000 + t2*100 + t1*10 + t0) event_date 
  FROM
    (SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
    (SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
    (SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
    (SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
    (SELECT 0 t4 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4
) AS date_range JOIN classes c 
  LEFT JOIN enrollment_changes AS e ON e.change_date <= date_range.event_date AND  c.id = e.class_id
WHERE date_range.event_date BETWEEN '2019-01-01' AND '2019-01-03'
GROUP BY date_range.event_date, c.name 
ORDER BY date_range.event_date, c.name
日历表上的每一天都使用JOIN与所有类联接。encrollment更改使用LEFT JOIN to The day和特定类进行连接。使用IFNULL可以将NULL值替换为0


仅在当天使用GROUP BY会导致每天生成一行。要获得每天每节课的一行,您必须按天和课名分组。

不确定我是否理解所需的结果。。为什么2019-01-03数学2?NetEnrollment的2值与同一组2019-01-03英语1 2019-01-03科学1的值相同,NetEnrollment的值仍然为1。我也希望在那里为2,因为英语和科学也有与数学相同的先前值?1日,数学的净注册为1。2日,数学没有变化,因此净入学人数仍然是1。3日,增加1名学生,净增2名。在我最初的帖子中,我省略了AND来将注册事件与类联系起来,这让事情变得很混乱。现在我明白了,但它在当前数据集上不起作用,因为在类id组中的change_date列中没有定义重复值的顺序。搞定了!我现在明白了。非常感谢。
event_date   name      NetEnrollment
------------------------------------
2019-01-01   math      1
2019-01-01   english   0
2019-01-01   science   0
2019-01-02   math      1
2019-01-02   english   1
2019-01-02   science   0
2019-01-03   math      2
2019-01-03   english   1
2019-01-03   science   1
SELECT date_range.event_date, c.name, IFNULL(SUM(e.change), 0) AS 'NetEnrollment'
FROM (
  SELECT adddate('1970-01-01',t4*10000 + t3*1000 + t2*100 + t1*10 + t0) event_date 
  FROM
    (SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
    (SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
    (SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
    (SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
    (SELECT 0 t4 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4
) AS date_range JOIN classes c 
  LEFT JOIN enrollment_changes AS e ON e.change_date <= date_range.event_date AND  c.id = e.class_id
WHERE date_range.event_date BETWEEN '2019-01-01' AND '2019-01-03'
GROUP BY date_range.event_date, c.name 
ORDER BY date_range.event_date, c.name