在两个单独的表中计算计划总额与实际总额
Posted
技术标签:
【中文标题】在两个单独的表中计算计划总额与实际总额【英文标题】:Calculate total scheduled against total actual in two separate tables 【发布时间】:2021-09-17 19:59:29 【问题描述】:我的架构中有两个表。第一个包含重复约会列表 - default_appointments
。第二个表是actual_appointments
- 这些可以从默认值生成或单独创建,因此不链接到任何默认条目。
例子:
default_appointments
id | day_of_week | user_id | appointment_start_time | appointment_end_time |
---|---|---|---|---|
1 | 1 | 1 | 10:00:00 | 16:00:00 |
2 | 4 | 1 | 11:30:00 | 17:30:00 |
3 | 6 | 5 | 09:00:00 | 17:00:00 |
actual_appointments
id | default_appointment_id | user_id | appointment_start | appointment_end |
---|---|---|---|---|
1 | 1 | 1 | 2021-09-13 10:00:00 | 2021-09-13 16:00:00 |
2 | NULL | 1 | 2021-09-13 11:30:00 | 2021-09-13 13:30:00 |
3 | 6 | 5 | 2021-09-18 09:00:00 | 2021-09-18 17:00:00 |
我希望根据实际创建/生成的总分钟数计算计划的总分钟数。所以最终我会得到一个包含这些数据的查询结果:
user_id | appointment_date | total_planned_minutes | total_actual_minutes |
---|---|---|---|
1 | 2021-09-13 | 360 | 480 |
1 | 2021-09-16 | 360 | 0 |
5 | 2021-09-18 | 480 | 480 |
这里最好的方法是什么?希望以上内容有意义。
编辑
好的,default_appointments
表包含所有“标准”的约会并且是自动生成的。这些是约会“应该”每周发生的事情。所以例如ID 1,此约会应在每周一上午 10 点至下午 4 点之间进行。 ID 2 应该出现在每周四上午 11:30 到下午 5:30 之间。
actual_appointments
表包含所有实际发生的约会的列表。基本上发生的事情是 default_appointment 在最初设置时会自动在actual_appointments
表中生成一个实例。相应的 default_appointment_id 表示它链接到默认值并且尚未更改 - 因此两者的时间将保持不变。用户可以随意更改这些已默认生成的约会,从而将 default_appointment_id 设置为 NULL * - 或 -* 可以添加与默认值无关的新约会。
所以,如果在星期一(day_of_week = 1)我通常应该在上午 10 点到下午 4 点有一个默认约会,那么我应该根据默认值计划的总分钟数是 360 分钟,无论实际约会表中的内容是什么,我应该为每周一的 360 分钟计划好。如果在系统中我说 - 实际上,我在上午 10 点到下午 4 点之间没有预约,而是将其更改为上午 10 点到下午 2 点,那么actual_appointments 表将包含当天的实际时间,并且指定的实际分钟数为 240 分钟。
我需要按日期和用户对每一项进行分组,以了解用户在default_appointments
表中计划约会的时间与他们实际约会的时间。
【问题讨论】:
scheduled
和created/generated
的概念不清楚。哪一行代表scheduled
约会,哪一行代表created/generated
约会?这是否都在基于default_appointment_id
是否为null
的actual_appointments
表中找到?
道歉。是的,actual_appointments
中的空值表示已手动创建的约会实例,因此不基于默认值。
好吧,那不是我的问题。你有一个scheduled
的概念。哪一行代表scheduled
约会?你能指出每个表中对应于你要计算的不同总和的行吗?考虑到这些数据,即使是一个带有数据的微小测试用例也可以提供您所期望的确切结果。
因此,actual_appointments
表中与 default_appointment_id
关联的任何约会都是在后台生成的 - 因此基本上是由后台作业安排和创建的。表中具有空值的任何其他实例都是由用户手动创建的。希望这是有道理的?
@DanielBarnes 。 . .对我来说,NULL
id 的实际约会如何与默认值匹配并不明显。或者默认指定的数据是如何变成日期的。有些事情没有得到解释。
【参考方案1】:
根据问题中的新细节进行了调整。 注意:我使用了与默认 mysql 行为兼容的 day_of_week 值,其中 Monday = 2。
第一个 CTE 术语 (args
) 提供搜索参数、开始日期和天数。第二个 CTE 术语 (drange
) 计算范围内的日期,以允许在该范围内生成已安排的约会。
allrows
通过UNION
结合预定和实际约会以准备聚合。还有其他设置方法。
最后,我们汇总每个 user_id 和 date 的结果。
测试用例:
Working Test Case (Updated)
WITH RECURSIVE args (startdate, days) AS (
SELECT DATE('2021-09-13'), 7
)
, drange (adate, days) AS (
SELECT startdate, days-1 FROM args UNION ALL
SELECT adate + INTERVAL '1' DAY, days-1 FROM drange WHERE days > 0
)
, allrows AS (
SELECT da.user_id
, dr.adate
, ROUND(TIME_TO_SEC(TIMEDIFF(da.appointment_end_time, da.appointment_start_time))/60, 0) AS planned
, 0 AS actual
FROM drange AS dr
JOIN default_appointments AS da
ON da.day_of_week = dayofweek(adate)
UNION
SELECT user_id
, DATE(appointment_start) AS xdate
, 0 AS planned
, TIMESTAMPDIFF(MINUTE, appointment_start, appointment_end)
FROM drange AS dr
JOIN actual_appointments aa
ON DATE(appointment_start) = dr.adate
)
SELECT user_id, adate
, SUM(planned) AS planned
, SUM(actual) AS actual
FROM allrows
GROUP BY adate, user_id
;
Result:
+---------+------------+---------+--------+
| user_id | adate | planned | actual |
+---------+------------+---------+--------+
| 1 | 2021-09-13 | 360 | 480 |
| 1 | 2021-09-16 | 360 | 0 |
| 5 | 2021-09-18 | 480 | 480 |
+---------+------------+---------+--------+
【讨论】:
以上是关于在两个单独的表中计算计划总额与实际总额的主要内容,如果未能解决你的问题,请参考以下文章
在Woocommerce电子邮件通知中将税总额添加为单独的行
Python描述 LeetCode 5259. 计算应缴税款总额