【问题标题】:Time calculation past midnight午夜过后的时间计算
【发布时间】:2012-12-31 17:25:57
【问题描述】:

我有一个按以下顺序存储时钟条目的表。

UID         Clock                    Status
===         =====                    ======

R01         2013-01-01 17:00:00      Clockin
R01         2013-01-01 17:10:00      Clockin
R01         2013-01-01 23:45:00      Clockin

我目前的解决方案是使用 Min/Max date with case 和 left join 按以下顺序排列条目

UID        Date         ClockIn    ClockOut
===        ====         =======    ========
R01        2013-01-01    17:00:00  23:45:00

当时钟输入跨越午夜时,我应该如何处理这种情况。即,

UID         Clock                    Status
===         =====                    ======
R01         2013-01-01 17:00:00      Clockin
R01         2013-01-02 00:45:00      Clockin

由于上述将产生 2 个如下条目,这将导致员工的零时间状态为 7.45 小时。

UID        Date          ClockIn               ClockOut
===        ====          =======               ========
R01        2013-01-01    2013-01-01 17:00:00   2013-01-01 17:00:00
R01        2013-01-02    2013-01-02 00:45:00   2013-01-02 00:45:00

提前致谢。

这是在 SQL 2008R2 中使用的存储过程的代码

SELECT A.Device,A.DID, A.Name, A.ClockDate,Clockin ,ClockOut
FROM 
(
    SELECT Device,DID,Name, CONVERT(DATE, DeviceClock) 'ClockDate', 
    min(case when clock=Clock and Status ='Clock In' OR status='Clock Out' OR status='Access In' then clock  end) 'CLock In'

    FROM TABLE  
    group by Device,DID,Name, CONVERT(DATE, DeviceClock)
) as A
LEFT JOIN 
(
    SELECT Device,DID,Name, CONVERT(DATE, DeviceClock) 'ClockDate', 

max(case when clock=Clock and Status ='Clock in' or status='Clock Out' OR status='Access In' then Clock end) 'Clock Out'


    FROM TABLE 
    group by Device,DID,Name, CONVERT(DATE, DeviceClock)
) as B
ON A.DID = B.DID AND A.ClockDate = B.ClockDate

【问题讨论】:

  • 请显示您现在使用的查询示例,以便我们提出替代方案。另外,请确定使用的数据库软件。
  • 似乎摆脱 Date 并让 ClockIn 和 ClockOut 成为完整的 DateTime 字段会容易得多。
  • 如果您还想跟踪日期,那么您可能需要使用composite key (UID+DATE)。否则乔丹所说的很合适。请澄清。
  • 是的。打卡和打卡存储在日期时间类型字段中。
  • @user1833676 嗨,我的考勤项目与我的情况相同。你找到解决办法了吗?非常感谢

标签: sql sql-server-2008 time-and-attendance


【解决方案1】:

这里有很多你没有考虑到的。时间/考勤系统非常复杂。例如:

  • 如果您的 ClockIn 仅在午夜前几分钟,而 ClockOut 则在早上很晚,该怎么办?您将时间记录到哪一天?
  • 如果时间平均分配,比如晚上 10 点到凌晨 2 点,那会是第 1 天的一个 4 小时轮班吗?还是第 2 天?还是两个 2 小时轮班?
  • 您是否使用 UTC 记录时间?进行本地转换?处理夏令时? (本地时间的输出减去输入不是对经过的持续时间的准确测量!)
  • 四舍五入?多少?在什么情况下?
  • 如何处理缺拳?重复出拳?

已经发展出完整的系统来处理这些场景。他们通常还处理工作规则,如加班计算、工作成本计算、调度和其他事情 - 但他们都从您描述的基本问题案例开始。

您并不总是与下一拳配对,或特定类型的下一拳,或同一日期的下一拳。有多种场景组合需要处理,你不能用简单的 sql 语句或存储过程来表达。您可以尝试 - 但您将有很多边缘情况需要处理。

我会考虑购买已经为您处理这些案件的产品。如果您打算自己编写 - 不要在 SQL 中编写。从 SQL 中获取原始数据并将其与您的业务逻辑一起使用以生成处理引擎。

【讨论】:

  • 嗨,马特·约翰逊。感谢您的输入。你提到的那些已经被注意到了。这种情况的事情是这样的。这些员工不按任何时间表工作,因为他们可以在没有固定时间或时间表的情况下来来去去。有些人一天可以上班两次,其中已经创建了分班制,并相应地调整了时间,并使用手动打孔输入来弥补任何错过的打孔。我们需要照顾的是那些在关闭期间工作到午夜的少数员工。因为目前的解决方案是使用手动打孔输入来调整他们的时间..
  • 不同的 T/A 系统以不同的方式处理这种情况。有些人在午夜切断了工作,并为第二天创造了一个新的班次。有些允许您重新打开已关闭的期间进行修改,有些则允许您对已关闭的期间进行修改作为下一个期间的调整。您如何定义“结束”与它有很大关系。
  • 我指的关闭是关闭店门。如前所述,没有明确的班次。员工晚上 10 点进来,工作到 00:45。他们的报酬是 2.45 小时。
【解决方案2】:

马特所说的是一个很好的一般性答案,并阅读了他提到的所有警告,但如果你的情况很简单,所有员工在早上 6 点之后开始,在午夜之前离开并在比如说凌晨 3 点之前完成,你可以捏造它很像这样:

SELECT Device,DID,Name, convert( DATE, dateadd(hour, -3, CONVERT(DATE, DeviceClock))) 'ClockDate', 

max(case when clock=Clock and Status ='Clock in' or status='Clock Out' OR status='Access In' then Clock end) 'Clock Out'

FROM TABLE 
group by Device,DID,Name, convert( DATE, dateadd(hour, -3, CONVERT(DATE, DeviceClock)))

在两个连接选择中的每一个中。你有效地将一天的开始和结束时间缩短了 3 个小时。当然,如果有人在凌晨 3 点以后工作,或者在凌晨 3 点之前开始工作,这将不起作用。

【讨论】:

  • 是的 - 这是另一种方法 - 自定义工作日截止时间。当您有人只是迟到(例如电影院)时,它可以工作,但它对于 24/7 运营(例如医院)存在问题。您可能需要一个可变的工作日线,每个员工或每个员工组都不同。如果他们在这条线上工作,你仍然需要知道如何处理。
  • 谢谢马特。您的意见很有价值。在我们的情况下,人们会迟到打扫卫生,不会超过凌晨 1 点。并感谢 Jonny 提出解决方案的建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多