在两个单独的表中计算计划总额与实际总额

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 表中计划约会的时间与他们实际约会的时间。

【问题讨论】:

scheduledcreated/generated的概念不清楚。哪一行代表scheduled 约会,哪一行代表created/generated 约会?这是否都在基于default_appointment_id 是否为nullactual_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 |
+---------+------------+---------+--------+

【讨论】:

以上是关于在两个单独的表中计算计划总额与实际总额的主要内容,如果未能解决你的问题,请参考以下文章

连接两个表并显示发票编号总额的 SQL 查询

外商投资企业之投资总额与注册资本的关系

在Woocommerce电子邮件通知中将税总额添加为单独的行

Python描述 LeetCode 5259. 计算应缴税款总额

如何在 WooCommerce 编辑订单中计算自定义订单总额?

使用flume在两个单独的表中写入hive仓库目录中的数据