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

我只是创建自己的示例来测试其他选项,而无需添加其他字段。

SQL Fiddle Demo

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 BYORDER BY