我正在使用 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 已经结束,它仍在继续增加。要纠正这一点,我们需要使用最小二乘的Day和End_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_Tasks和Days_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 评论