拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 MySQL-任务管理器-S-Curve-总结任务

MySQL-任务管理器-S-Curve-总结任务

白鹭 - 2022-01-26 2107 0 0

我正在使用 PHP 和 MySQL 以及其他语言构建项目管理器系统,并且我正在努力查询我的资料以创建 S 曲线图。在我的数据库中,我有下表名为“任务”

ID 任务 开始日期 结束日期 地位
1 任务1 2021-12-01 2021-12-06 悬垂
2 任务 2 2021-12-02 2021-12-07 完全的
3 任务 3 2021-12-03 2021-12-07 完全的

要绘制图表,我需要在任务表表的最小日期和最大日期之间每天都有一行,即使任务表中不存在此确切日期(例如:2021-12-04 - 它没有写在桌子上,但它发生在 2021-12-01 和 2021-12-07 之间)。而且,对于每一天,我需要计算日期之前存在的所有任务的持续时间,并且仅对已完成的任务计算相同的持续时间(我将尝试用示例更好地解释):

天_任务 Days_Tasks_Completed 观察:
2021-12-01(任务表第一天) 1 0 计数:只有一天的任务1
2021-12-02 3 1 Days_Task: 2 天的task1 1 天的 task2 Completed_Taks: 1 天的 Task2
2021-12-03 6 3 Days_Task: 3 天的task1 2d 的 task2 1d task3 Completed_Taks: 2 天的 Task2 和 1d task3(它不计算 task1 的天数,因为它没有“完成”
2021-12-04 9 5 Days_Task:4天的task1加上3d的task2加上2d的task3 Completed_Taks: 3d的task2和2d的task3
2021-12-05 12 7 Days_Task:task1 的5d 加上 task2 的 4d 加上 3d task3 Completed_Taks: task2 的 4d 加上 3d task3
2021-12-06 15 9 Days_Task:task1 的6d 加上 task2 的 5d 加上 4d task3 Completed_Taks: task2 的 5d 加上 4d task3
2021-12-07(最后一天) 17 11 Days_Task:task1 的6d 加上 task2 的 6d 加上 5d task3 Completed_Taks:task2 的 6d 加上 5d task3

说明:最后一天 (2020-12-07) 是出现在任务表上的最后一天。对于那一天,我要数 17 个“天数任务”(任务 1 为 6 天,因为所有 6 天的持续时间都发生在 2020 年 12 月 7 日之前 任务 2 的所有天数 持续时间为任务 3) 已完成的“天数任务”也是如此,但只计算已完成任务的天数 - 因此,不考虑任务 1,因为它是“待定”)。

老实说,我不知道如何使用 MySQL 执行该操作。我尝试了一堆查询,但似乎没有任何效果如我所愿。

我能够使用以下方法获得包含所有日期的表格:

@i<-1;
SELECT DATE(ADDDATE((SELECT MIN(Beginning_Date) from tasks), INTERVAL @i:=@i 1 DAY)) AS date FROM `tasks`
HAVING 
@i < DATEDIFF((SELECT MAX(End_date) from tasks), (SELECT MIN(Beginning_Date) from tasks )))

但是,我不知道如何计算这些日期的任务。

有谁知道该怎么做?

uj5u.com热心网友回复:

您的所需输出表中似乎存在一些错误。如果我理解正确,以下查询有效,但这需要 MySQL 8。第一个CTE是您的示例资料。第二个 CTE 是递回 CTE,用于提供日期范围然后查询根据日期和状态进行一些聚合。

WITH RECURSIVE `Tasks` (`ID`, `Task`, `Beginning_Date`, `End_date`, `Status`) AS
(
    SELECT 1, 'Task-1', DATE('2021-12-01'), DATE('2021-12-06'), 'Pendent' UNION ALL
    SELECT 2, 'Task-2', DATE('2021-12-02'), DATE('2021-12-07'), 'Completed' UNION ALL
    SELECT 3, 'Task-3', DATE('2021-12-03'), DATE('2021-12-07'), 'Completed'
),
`dates` (`date`) AS
(
  SELECT MIN(`Beginning_Date`) FROM `Tasks`
  UNION ALL
  SELECT `date`   INTERVAL 1 DAY FROM `dates`
  WHERE `date`   INTERVAL 1 DAY <= (SELECT MAX(`End_date`) FROM `Tasks`)
)
SELECT
    `d`.`date` AS `Day`,
    SUM(DATEDIFF(LEAST(`d`.`date`, `t`.`End_date`), `t`.`Beginning_Date`)   1) AS `Days_Tasks`,
    SUM(IF(`t`.`Status` = 'Completed', DATEDIFF(LEAST(`d`.`date`, `t`.`End_date`), `t`.`Beginning_Date`)   1, 0)) AS `Days_Tasks_Completed`
FROM `dates` `d`
INNER JOIN `Tasks` `t` ON `t`.`Beginning_Date` <= `d`.`date`
GROUP BY `d`.`date`
ORDER BY `d`.`date`;

这是一个db<>fiddle

为了更好地理解正在发生的事情,我们可以只查看 Task-1 的 JOIN 结果

/* The CTEs are as above but left out for brevity */
SELECT
    `d`.`date` AS `Day`, t.*,
    /*
        we need to add one as MAX Days_Tasks is inclusive
        of Beginning_Date and End_date
    */
    DATEDIFF(`d`.`date`, `t`.`Beginning_Date`)   1 AS `Days_Tasks_1`,
    /*
        we need to use the LEAST of d.date and t.End_date so
        we do not continue to count days beyond the t.End_date
    */
    DATEDIFF(LEAST(`d`.`date`, `t`.`End_date`), `t`.`Beginning_Date`)   1 AS `Days_Tasks_2`
FROM `dates` `d`
INNER JOIN `Tasks` `t` ON `t`.`Beginning_Date` <= `d`.`date`
WHERE `t`.`ID` = 1
ORDER BY `d`.`date` ASC;

回传 -

ID 任务 开始日期 结束日期 地位 Days_Tasks_1 Days_Tasks_2
2021-12-01 1 任务1 2021-12-01 2021-12-06 悬垂 1 1
2021-12-02 1 任务1 2021-12-01 2021-12-06 悬垂 2 2
2021-12-03 1 任务1 2021-12-01 2021-12-06 悬垂 3 3
2021-12-04 1 任务1 2021-12-01 2021-12-06 悬垂 4 4
2021-12-05 1 任务1 2021-12-01 2021-12-06 悬垂 5 5
2021-12-06 1 任务1 2021-12-01 2021-12-06 悬垂 6 6
2021-12-07 1 任务1 2021-12-01 2021-12-06 悬垂 7 6

Days_Tasks_1 看起来不错,直到我们到达最后一行,即使 Task-1 已经结束,它仍在继续增加。要纠正这一点,我们需要使用最小二乘DayEnd_date,所以我们不要继续超出任务的END_DATE。见 Days_Tasks_2

现在,如果我们仅查看 2021-12-07 天的 JOIN 结果

/* CTEs omitted as above */
SELECT
    `d`.`date` AS `Day`, t.*,
    DATEDIFF(LEAST(`d`.`date`, `t`.`End_date`), `t`.`Beginning_Date`)   1 AS `Days_Tasks`,
    IF(`t`.`Status` = 'Completed', DATEDIFF(LEAST(`d`.`date`, `t`.`End_date`), `t`.`Beginning_Date`)   1, 0) AS `Days_Tasks_Completed`
FROM `dates` `d`
INNER JOIN `Tasks` `t` ON `t`.`Beginning_Date` <= `d`.`date`
WHERE `d`.`date` = '2021-12-07'
ORDER BY `t`.`ID` ASC;

回传 -

ID 任务 开始日期 结束日期 地位 天_任务 Days_Tasks_Completed
2021-12-07 1 任务1 2021-12-01 2021-12-06 悬垂 6 0
2021-12-07 2 任务 2 2021-12-02 2021-12-07 完全的 6 6
2021-12-07 3 任务 3 2021-12-03 2021-12-07 完全的 5 5

您可以在此处查看Observation:示例列中所述的计数随着分组Day和SUMDays_TasksDays_Tasks_Completed可以看到的结果期望。

# 日 天_任务 Days_Tasks_Completed
2021-12-01 1 0
2021-12-02 3 1
2021-12-03 6 3
2021-12-04 9 5
2021-12-05 12 7
2021-12-06 15
标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *