按月分组并显示剩余的总天数

时间:2015-06-14 17:23:42

标签: mysql

我想列出按月分组以及在下一栏中完成课程的剩余天数。课程有10天。

示例数据

ID Name Date 
1 Sandy 2015-05-06 
2 Candy 2015-05-06 
3 Sandy 2015-05-28 
4 Candy 2015-05-29
5 Candy 2015-06-01

首选输出

| Name | Month | Attended | Remaining|
| Sandy| May   |   2      |     8    |
| Candy| May   |   2      |     8    |
| Candy| June  |   1      |     7    |

如果我使用GROUP BY DATE_FORMAT(日期,'%Y%m'),名称并尝试进行计算则不起作用。

1 个答案:

答案 0 :(得分:0)

您需要两种不同的聚合:

  1. 指定用户当月参加的天数。
  2. 在指定用户的当月之前的所有月份中参加的天数。
  3. 这有点繁琐,所以现在是时候做一些测试驱动的查询设计(TDQD)。

    问题中的表格是匿名的 - 这是一种常见且令人不快的情况。因此,该表从此为CourseAttendance,数据中显示了三列(ID,名称,日期)。

    用户在特定月份参加的天数

    假设表达式DATE_FORMAT(date, '%Y-%m')在语法上有效,并且DateMonth作为列名称都不会导致问题,那么:

    SELECT DATE_FORMAT(Date, '%Y-%m') AS Month,
           Name,
           COUNT(*) AS NumDays
      FROM CourseAttendance
     GROUP BY Month, Name
    

    这应该产生:

    Month     Name      NumDays
    2015-05   Sandy     2
    2015-05   Candy     2
    2015-06   Candy     1
    

    用户在特定月份(包括特定月份)参与的天数

    这次,汇总必须超过所有日期小于或等于转换月份值:

    SELECT D.Month, D.Name, SUM(C.NumDays) AS TotDays
      FROM (SELECT DISTINCT DATE_FORMAT(Date, '%Y-%m') AS Month, Name
              FROM CourseAttendance
           ) AS D
      JOIN (SELECT DATE_FORMAT(Date, '%Y-%m') AS Month,
                   Name,
                   COUNT(*) AS NumDays
              FROM CourseAttendance
             GROUP BY Month, Name
           ) AS C
        ON C.Month <= D.Month AND C.Name = D.Name
     GROUP BY D.Month, D.Name
    

    这应该给出输出:

    Month     Name      NumDays
    2015-05   Sandy     2
    2015-05   Candy     2
    2015-06   Candy     3
    

    汇总最终结果

    前两个结果表需要在Month和Name上连接,以产生结果:

    SELECT A.Name, A.Month, A.NumDays AS Attended, (10 - B.TotDays) AS Remaining
      FROM (SELECT DATE_FORMAT(Date, '%Y-%m') AS Month,
                   Name,
                   COUNT(*) AS NumDays
              FROM CourseAttendance
             GROUP BY Month, Name
           ) AS A
      JOIN (SELECT D.Month, D.Name, SUM(C.NumDays) AS TotDays
              FROM (SELECT DISTINCT DATE_FORMAT(Date, '%Y-%m') AS Month, Name
                      FROM CourseAttendance
                   ) AS D
              JOIN (SELECT DATE_FORMAT(Date, '%Y-%m') AS Month,
                           Name,
                           COUNT(*) AS NumDays
                      FROM CourseAttendance
                     GROUP BY Month, Name
                   ) AS C
                ON C.Month <= D.Month AND C.Name = D.Name
             GROUP BY D.Month, D.Name
           ) AS B
        ON A.Month = B.Month AND A.Name = B.Name
     ORDER BY A.Name, A.Month
    

    这应该输出如下:

    Name      Month      Attended     Remaining
    Candy     2015-05    2            8
    Candy     2015-06    1            7
    Sandy     2015-05    2            8
    

    如果需要,您可以将月份值伪装成月份名称。如果您想在月份内使用月份和名称等,也可以获取排序顺序