MySQL:使用排序月份的 GROUP BY 计算 运行 总数
MySQL: Calculate a Running Total Using a GROUP BY Using Ordered Month
我正在尝试使用几个月来完成 运行 总数。这是我正在做的部分工作的简化版本:
SELECT
MONTHNAME(STR_TO_DATE(DateContacted,'%m/%d/%Y')) AS MONTH,
IFNULL(COUNT(CASE WHEN s.surveyid = 649814 THEN s.id ELSE NULL END),0) Signer,
(SELECT COUNT(s2.id) FROM sq s2
WHERE s2.surveyid = 649814 AND MONTHNAME(STR_TO_DATE(s2.DateContacted,'%m/%d/%Y')) <= MONTH
GROUP BY MONTH
ORDER BY MONTH) RT
FROM
sq s
GROUP BY MONTH
ORDER BY MONTH
但问题是订单已关闭,当您尝试执行 运行 总计时,这显然是个大问题:
MONTH Signer RT
April 1646 1646
August 81 1727
December 0 1727
February 0 1727
January 0 1727
July 24 1751
June 241 1992
March 2120 4112
May 115 4227
November 28 4255
October 173 4428
September 73 4501
但是当我尝试这样正确地排序时:
SELECT
MONTHNAME(STR_TO_DATE(DateContacted,'%m/%d/%Y')) AS MONTH,
IFNULL(COUNT(CASE WHEN s.surveyid = 649814 THEN s.id ELSE NULL END),0) Signer,
(SELECT COUNT(s2.id) FROM sq s2
WHERE s2.surveyid = 649814 AND MONTHNAME(STR_TO_DATE(s2.DateContacted,'%m/%d/%Y')) <= MONTH
GROUP BY MONTH
ORDER BY FIELD(MONTH,'January','February','March','April','May','June','July','August','September','October','November','December')) RT
FROM
sq s
GROUP BY MONTH
ORDER BY FIELD(MONTH,'January','February','March','April','May','June','July','August','September','October','November','December')
它丢弃了所有 RT 计数(尽管 Signer 计数是正确的):
MONTH Signer RT
January 0 1727
February 0 1727
March 2120 4112
April 1646 1646
May 115 4227
June 241 1992
July 24 1751
August 81 1727
September 73 4501
October 173 4428
November 28 4255
December 0 1727
我使用此方法而不是子查询,因为这通常是一个更大的查询的一部分,我 LEFT JOIN
两个 table 按月在一起。不幸的是,我似乎也不能使用 @runtot variable solution,因为这需要在最后按月进行 GROUPed 并且将其关闭。我知道 MySQL 对于这种功能来说并不完美,但我似乎很接近,如果这可以与我的其余查询一起放在同一个地方,那就太好了。感谢您的帮助!
编辑:
这是理想的结局-table:
MONTH Signer RT
January 0 0
February 0 0
March 2120 2120
April 1646 3766
May 115 3881
June 241 4122
July 24 4146
August 81 4227
September 73 4300
October 173 4473
November 28 4501
December 0 4501
你能添加附加字段吗monthid
?
SELECT
MONTH(STR_TO_DATE(DateContacted,'%m/%d/%Y')) AS MONTHID,
MONTHNAME(STR_TO_DATE(DateContacted,'%m/%d/%Y')) AS MONTH,
IFNULL(COUNT(CASE WHEN s.surveyid = 649814 THEN s.id ELSE NULL END),0) Signer,
(SELECT COUNT(s2.id)
FROM sq s2
WHERE s2.surveyid = 649814
AND MONTH(STR_TO_DATE(s2.DateContacted,'%m/%d/%Y')) <= MONTHID
GROUP BY MONTHID, MONTH
ORDER BY MONTHID) RT
FROM
sq s
GROUP BY MONTHID, MONTH
ORDER BY MONTHID
我只是创建自己的示例来测试其他选项,而无需添加其他字段。
SELECT MONTHNAME(`date`) as MONTH,
IFNULL(COUNT(CASE WHEN `sales` % 3 = 0 THEN 1 ELSE NULL END),0) as SIGNER,
(SELECT COUNT(s2.`sales`)
FROM Table1 s2
WHERE
s2.`sales` % 3 = 0
AND MONTH(`date`) <= MONTH(s.`date`)
GROUP BY MONTH
ORDER BY MONTH) RT
FROM
Table1 s
GROUP BY MONTH(`date`)
ORDER BY MONTH(`date`)
输出
| MONTH | SIGNER | RT |
|----------|--------|----|
| January | 2 | 2 |
| February | 3 | 5 |
| March | 2 | 7 |
| April | 2 | 9 |
| May | 1 | 10 |
| June | 1 | 11 |
| July | 2 | 13 |
| August | 1 | 14 |
| December | 1 | 15 |
注意:
完成示例后,我意识到我的 12 月是 2014 年的,其余的是 2015 年的。所以请小心过滤 YEAR = 2015
没有理由在子查询中使用order by
。也不去复杂order by
。相反:
SELECT MONTHNAME(STR_TO_DATE(DateContacted, '%m/%d/%Y')) AS MONTH,
SUM(s.surveyid = 649814) as Signer,
(SELECT COUNT(s2.id)
FROM sq s2
WHERE s2.surveyid = 649814 AND
DATE_FORMAT(STR_TO_DATE(s2.DateContacted, '%m/%d/%Y'), '%Y-%m') <= DATE_FORMAT(STR_TO_DATE(s.DateContacted, '%m/%d/%Y'), '%Y-%m')
)
FROM sq s
GROUP BY DATE_FORMAT(STR_TO_DATE(s.DateContacted, '%m/%d/%Y'), '%Y-%m')
ORDER BY MIN(STR_TO_DATE(DateContacted, '%m/%d/%Y'));
备注:
- 将日期存储为字符串是个坏主意。
- 以 YYYYMMDD 或 YYYY-MM-DD 以外的任何格式将日期存储为字符串是一个更糟糕的主意。
- 将这样的专栏称为 "date" 真的非常糟糕。
- 无论如何,
ORDER BY
不需要一些复杂的月份名称列表。您可以简单地使用一个月中的任何日期(MIN()
很方便)。
- 同样,每月的比较和聚合也可以只使用YYYY-MM格式。
- 子查询不应有
GROUP BY
或 ORDER BY
。
我正在尝试使用几个月来完成 运行 总数。这是我正在做的部分工作的简化版本:
SELECT
MONTHNAME(STR_TO_DATE(DateContacted,'%m/%d/%Y')) AS MONTH,
IFNULL(COUNT(CASE WHEN s.surveyid = 649814 THEN s.id ELSE NULL END),0) Signer,
(SELECT COUNT(s2.id) FROM sq s2
WHERE s2.surveyid = 649814 AND MONTHNAME(STR_TO_DATE(s2.DateContacted,'%m/%d/%Y')) <= MONTH
GROUP BY MONTH
ORDER BY MONTH) RT
FROM
sq s
GROUP BY MONTH
ORDER BY MONTH
但问题是订单已关闭,当您尝试执行 运行 总计时,这显然是个大问题:
MONTH Signer RT
April 1646 1646
August 81 1727
December 0 1727
February 0 1727
January 0 1727
July 24 1751
June 241 1992
March 2120 4112
May 115 4227
November 28 4255
October 173 4428
September 73 4501
但是当我尝试这样正确地排序时:
SELECT
MONTHNAME(STR_TO_DATE(DateContacted,'%m/%d/%Y')) AS MONTH,
IFNULL(COUNT(CASE WHEN s.surveyid = 649814 THEN s.id ELSE NULL END),0) Signer,
(SELECT COUNT(s2.id) FROM sq s2
WHERE s2.surveyid = 649814 AND MONTHNAME(STR_TO_DATE(s2.DateContacted,'%m/%d/%Y')) <= MONTH
GROUP BY MONTH
ORDER BY FIELD(MONTH,'January','February','March','April','May','June','July','August','September','October','November','December')) RT
FROM
sq s
GROUP BY MONTH
ORDER BY FIELD(MONTH,'January','February','March','April','May','June','July','August','September','October','November','December')
它丢弃了所有 RT 计数(尽管 Signer 计数是正确的):
MONTH Signer RT
January 0 1727
February 0 1727
March 2120 4112
April 1646 1646
May 115 4227
June 241 1992
July 24 1751
August 81 1727
September 73 4501
October 173 4428
November 28 4255
December 0 1727
我使用此方法而不是子查询,因为这通常是一个更大的查询的一部分,我 LEFT JOIN
两个 table 按月在一起。不幸的是,我似乎也不能使用 @runtot variable solution,因为这需要在最后按月进行 GROUPed 并且将其关闭。我知道 MySQL 对于这种功能来说并不完美,但我似乎很接近,如果这可以与我的其余查询一起放在同一个地方,那就太好了。感谢您的帮助!
编辑:
这是理想的结局-table:
MONTH Signer RT
January 0 0
February 0 0
March 2120 2120
April 1646 3766
May 115 3881
June 241 4122
July 24 4146
August 81 4227
September 73 4300
October 173 4473
November 28 4501
December 0 4501
你能添加附加字段吗monthid
?
SELECT
MONTH(STR_TO_DATE(DateContacted,'%m/%d/%Y')) AS MONTHID,
MONTHNAME(STR_TO_DATE(DateContacted,'%m/%d/%Y')) AS MONTH,
IFNULL(COUNT(CASE WHEN s.surveyid = 649814 THEN s.id ELSE NULL END),0) Signer,
(SELECT COUNT(s2.id)
FROM sq s2
WHERE s2.surveyid = 649814
AND MONTH(STR_TO_DATE(s2.DateContacted,'%m/%d/%Y')) <= MONTHID
GROUP BY MONTHID, MONTH
ORDER BY MONTHID) RT
FROM
sq s
GROUP BY MONTHID, MONTH
ORDER BY MONTHID
我只是创建自己的示例来测试其他选项,而无需添加其他字段。
SELECT MONTHNAME(`date`) as MONTH,
IFNULL(COUNT(CASE WHEN `sales` % 3 = 0 THEN 1 ELSE NULL END),0) as SIGNER,
(SELECT COUNT(s2.`sales`)
FROM Table1 s2
WHERE
s2.`sales` % 3 = 0
AND MONTH(`date`) <= MONTH(s.`date`)
GROUP BY MONTH
ORDER BY MONTH) RT
FROM
Table1 s
GROUP BY MONTH(`date`)
ORDER BY MONTH(`date`)
输出
| MONTH | SIGNER | RT |
|----------|--------|----|
| January | 2 | 2 |
| February | 3 | 5 |
| March | 2 | 7 |
| April | 2 | 9 |
| May | 1 | 10 |
| June | 1 | 11 |
| July | 2 | 13 |
| August | 1 | 14 |
| December | 1 | 15 |
注意:
完成示例后,我意识到我的 12 月是 2014 年的,其余的是 2015 年的。所以请小心过滤 YEAR = 2015
没有理由在子查询中使用order by
。也不去复杂order by
。相反:
SELECT MONTHNAME(STR_TO_DATE(DateContacted, '%m/%d/%Y')) AS MONTH,
SUM(s.surveyid = 649814) as Signer,
(SELECT COUNT(s2.id)
FROM sq s2
WHERE s2.surveyid = 649814 AND
DATE_FORMAT(STR_TO_DATE(s2.DateContacted, '%m/%d/%Y'), '%Y-%m') <= DATE_FORMAT(STR_TO_DATE(s.DateContacted, '%m/%d/%Y'), '%Y-%m')
)
FROM sq s
GROUP BY DATE_FORMAT(STR_TO_DATE(s.DateContacted, '%m/%d/%Y'), '%Y-%m')
ORDER BY MIN(STR_TO_DATE(DateContacted, '%m/%d/%Y'));
备注:
- 将日期存储为字符串是个坏主意。
- 以 YYYYMMDD 或 YYYY-MM-DD 以外的任何格式将日期存储为字符串是一个更糟糕的主意。
- 将这样的专栏称为 "date" 真的非常糟糕。
- 无论如何,
ORDER BY
不需要一些复杂的月份名称列表。您可以简单地使用一个月中的任何日期(MIN()
很方便)。 - 同样,每月的比较和聚合也可以只使用YYYY-MM格式。
- 子查询不应有
GROUP BY
或ORDER BY
。