我正在使用 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 评论