在同一天的同一个人的多个记录中分配时间(循环)

Posted

技术标签:

【中文标题】在同一天的同一个人的多个记录中分配时间(循环)【英文标题】:Distribute time among multiple records for same person for same day (loop) 【发布时间】:2017-09-08 15:17:30 【问题描述】:

* 更新请求 *

我的记录显示了少数员工的一些工作时间,大多数情况下他们每天只有一个记录,即 REG,有时他们每天会有多个记录,例如 REG 和 OT 或 REG、OT、和OT1。我的任务的第一部分是计算小时数并将小时数与另一个表(包括休息时间)匹配并采用相应的休息时间,然后从实际小时数中扣除休息时间并显示结果。我已经成功地做到了这一点。 任务的第二部分是如果每天有超过 1 条记录,例如 REG、OT 或 REG、OT、OT1,那么我必须总结总小时数 (reg,ot,ot1) 然后休息表格并找到相应的休息时间,然后将休息时间(休息时间/60)乘以当天的每条记录,然后除以总和,取该值并从实际金额中减去该值。以下是示例(我猜我需要某种循环)

小时数据表

EMP_ID 日期 小时 类型 小时 -------- ---------- ---------- ---------- 1234 8/1/17 注册 8 2345 8/1/17 注册 5 3456 8/1/17 注册 8 3456 17 年 8 月 1 日 OT 1 4567 8/1/17 注册 8 4567 17 年 8 月 1 日 OT 1 4567 17 年 8 月 1 日 OT1 2

分解数据表

HOUR_TYPE FROM_HR_1 TO_HR_1 BREAK_IN_MIN_1 FROM_HR_2 TO_HR_2 BREAK_IN_MIN_2 FROM_HR_2 TO_HR_2 BREAK_IN_MIN_2 ----------- ---------- --------- --------------- ----- ----- --------- ---------------- ---------- --------- -- ------------- 注册 0 5 20 6 8 40 9 12 60 旧约 0 5 0 6 8 40 9 12 60 OT1 0 5 0 6 8 0 9 12 40

当前结果表

EMP_ID 日期时间类型 ACT_HOUR ADJ_HOUR -------- ---------- ---------- --------- --------- 1234 8/1/17 注册 8 7.34 2345 8/1/17 REG 5 4.67 3456 8/1/17 REG 8 7.34 3456 17 年 8 月 1 日 OT 1 1 4567 8/1/17 注册 8 7.34 4567 17 年 8 月 1 日 OT 1 1 4567 17 年 8 月 1 日 OT1 2 2

预期结果表

EMP_ID 日期时间类型 ACT_HOUR ADJ_HOUR -------- ---------- ---------- --------- --------- 1234 8/1/17 注册 8 7.34 2345 8/1/17 REG 5 4.67 3456 8/1/17 REG 8 7.12 3456 17 年 8 月 1 日 OT 1 .89 4567 8/1/17 注册 8 7.28 4567 17 年 8 月 1 日 OT 1 .91 4567 17 年 8 月 1 日 OT1 2 1.82

正如你所看到的“预期结果表”,我需要根据上述公式进行休息时间拆分 提前感谢您帮助我解决这个问题。

【问题讨论】:

为什么结果 adj_hour 第 3 行和第 5 行变成了 6.30?不应该是 7.30(7 小时 30 分钟/7.5 小时)吗? @FerdinandGaspar 你完全正确!!!这是我的一个错误 你在破表中没有OT和OT1的记录吗,只有REG? 是的,但是如果超过 5 小时的话。 【参考方案1】:

因为您不能在更新查询中使用聚合函数,所以您需要使用派生表(子查询也可以)。我的回答假设您有一个 hours 表和一个 breaks 表,并且每个员工/日期都有一行休息时间。

尝试以下方法:

update 
    hours
set
    ADJ_HOUR = 
    round(
        ADJ_HOUR -
            -- Build the value to subtract from ADJ_HOUR:
            (
                (b.BREAK_IN_MIN_1 + b.BREAK_IN_MIN_2) -- Sum of the breaks
                / (convert(float, cnt.total_rows) -- Divide the minutes by the num of "hours" rows
            )
            / convert(float, 60) -- Divide the subtract amount by 60 (minutes)
    , 1) -- Round to 1 decimal place
from 
    hours h
    join breaks b 
        on (h.employee=b.employee and h.date=b.date) -- Get the breaks for each employee
     -- Get the num of hour rows:
    join (select employee, date, count(*) as total_rows from hours group by employee_date) as cnt 
        on (h.employee=cnt.employee and h.date=cnt.date)

关于所有convert(float...) 调用的注意事项:在进行除法时,您希望浮点值来自两个整数的除法,您需要将其中一个值转换/转换为浮点数。否则,优化器将数据类型设置为与两个分割值相同(两个 int 数据类型产生一个 int)。

【讨论】:

谢谢 RToyota,正如你所见,我确实有一张表,其中包含所有带有员工日期的小时表和一个单独的休息表,其中只有一般时间,而不是特定于 emp。我将数据插入到具有组合结果的第三个表中。我当前的结果集正在进行必要的分钟到小时的转换,减去小时的分钟并添加到调整后的列。我遇到的问题是当一天有超过 1 条记录时,我不确定如何均匀分配时间。我会看看你的解决方案,让你知道我是怎么做的 不幸的是,这对我不起作用。因为我的 Break 表没有员工 ID。它是一个通用参考表。例如,如果我的小时数是“小时表”中的 8 小时,那么我会尝试查看我的 8 小时数是否低于分钟表中的给定小时数,它确实需要该行的分钟数并进行数学运算。

以上是关于在同一天的同一个人的多个记录中分配时间(循环)的主要内容,如果未能解决你的问题,请参考以下文章

ORACLE:在同一条语句中分配和检查

在单个代码行 C# 中分配多个变量

AppDomain 地址空间

如何在循环Django中分配外键

将(很多!)数字转换为字符串的正确方法,无需在 Qt 中分配

如果我在 C++ 中的一个线程中分配内存,我可以在另一个线程中取消分配它吗