工作/项目时间数据库 - 编辑记录

时间:2011-01-26 21:34:44

标签: database-design

我整理了一个非常简单的工作/项目打卡/时钟,供员工进出。每行包含一个输入和输出。然而,有时员工忘记在适当的时间打卡或打卡,所以我必须修改他们的拳头。

我的问题是:如何检查以确保我要做的更改与现有的打孔不重叠?

修改

表格看起来像这样:

Punch ID,Project Number,Employee ID,DateTime In,DateTimeOut
138,PA15212,1234,1/1/2010 1:00,1/1/2010 5:45
139,AD15217,5678,1/1/2010 1:00,1/1/2010 3:15
140,SL15222,4567,1/1/2010 1:00,1/1/2010 2:30
141,GA15151,5678,1/1/2010 3:20,1/1/2010 5:45

编辑2

为了澄清,正如我在下面的评论中所说,数据库是工作/项目时间跟踪系统。员工基本上都是打工。一旦他们这样做,他们唯一的选择是打出来。然后他们可以进入他们工作的下一份工作......并且将在一天中完成这项工作。在同一记录上输入和输出是一个简单/简单的系统,可以轻松匹配IN和OUT打孔以及计算该记录中的时间。然而,有时候他们会忘记投入工作,最终会这么做,或者忘了打出去。我需要修改那些拳,但我想确保更改不与该员工的现有进/出时间框架重叠。

8 个答案:

答案 0 :(得分:2)

我认为你试图将太多东西组合到一个表中,这使得这更复杂。提出的设计的一个主要问题是没有审计跟踪,因此如果存在账单或员工争议,则很难证明数据是有效的。

我建议使用一个真实的交易日志(仅限选择/插入),记录正在计算时间的人和输入数据的人以及导出摘要信息的数据视图正在寻找。然后,您可以通过遍历日志来查看相邻事件(“打孔”)来检查冲突。

答案 1 :(得分:1)

FWIW我认为你应该只捕捉实际发生的事情,如果有人忘记打卡或打卡,那么应该没有相应的条目。

如果您对实际发生的事情进行建模,那么您可以随时根据业务规则在应用程序中或通过存储过程创建缺失数据的默认值。这也允许您更改默认值,因为您总是计算它们。另外,它允许报告/统计等发生这种情况,谁是罪犯等等。再加上,重要的是你的数据库代表了真正发生的事情,而不是一些软糖。

PunchID, EmployeeID, ProjectNbr, Timestamp, Direction
111, 111, 101, 1/1/11 8:00, IN
111, 111, 101, 1/1/11 17:00, OUT

答案 2 :(得分:1)

用于查找重叠记录的SQL(诀窍是将表连接到自身):

SELECT * 
  FROM TABLE_XXX x1, TABLE_XXX x2 
 WHERE x1.employee_id = x2.employee_id
   AND x1.DateTimeIn < x2.DateTimeIn
   AND x1.DateTimeOut > x2.DateTimeIn
   AND x1.DateTimeIn > ?  -- start of the day in question
   AND x1.DateTimeIn < ?  -- end of the day in question
   AND EMPLOYEE_ID = ?

我的2c设计:

  1. 如果保留当前设计,则应创建插入和更新触发器,以检查重叠并在创建异常时抛出异常。

  2. 仅存储PerformanceDBA建议的每个活动的开始时间。这意味着你必须有一个特殊的项目来打孔。你可以通过插入缺失拳击的时间来修复错过的拳击。 该解决方案还将确保在有意的时间内没有漏洞(活动是特殊的“打卡”活动)。 这是最好的设计恕我直言。

答案 3 :(得分:0)

  1. “桌子”有几个问题会让你感到困难。

    • 失踪之拳的价值是什么?你是如何为那些打了一拳而没有打出来的员工生成或默认的?空值 ? 23:59? DateTimeIn?它们都是不正确的,但您必须具有一些已知值。)

    • 当你回答这个问题时,我们可以编写SQL代码(它确实是一个SQL问题)。

    • 您想用以下内容更新缺少的Punch OUT时间的价值:

    • 下次开始时间减去5分钟

    • 哪里没有下一个开始时间? 17:00?
  2. 关于AFA数据库设计,并没有看到其他表,该表应如下所示。假设他们为每个项目打了IN和OUT(工作?)。

    CREATE TABLE Punch (
        PunchID,        -- No idea what use it has, but I will keep it anyway
        ProjectNo,
        EmployeeID,
        DateTime,
        IsStart     BIT -- boolean, tinyint
        )

    • 当Punch IN发生时,Punch OUT没有发生,因此您存储的任何值都是错误的。

    • 缺少行很容易识别

  3. 前端,GUI,基于字符的命令,无论如何,都可以使用一些改进。

    • 它应该明确地打入IN或OUT

    • 当注册Punch IN时,如果没有先前的Punch OUT,则可以使用一系列默认值,并首先创建Punch OUT。例如,当天:使用当前日期时间,第二天:使用前一天的17:00。

答案 4 :(得分:0)

这是我对你的问题增加清晰度的看法。评论我错误地理解并错过了什么。我会尝试不断修改。

您正在寻找“Punch”事件中两个例外的解决方案。您想要涵盖的两个例外是:

  1. 一名员工打了一拳,但今天早上忘记了打击

  2. 一名员工打了一拳,但忘了昨天打出

    • 对于第一个例外,您可以用来创建逻辑的信息是当前的打孔时间。如果当前时间比较晚,比如12点,那么今天9点钟就会填满一个标准的打卡。

    • 第二拳可以类似地处理;如果当前时间是晚上03点,那么员工可能已经忘记了昨天的打击。

  3. 正如您可能看到的那样,我明白这个简单的逻辑可能不是您正在寻找的答案。但请评论我在这里错过的内容,我会根据您的需要对其进行修改。

答案 5 :(得分:0)

psuedo代码如何:

onPunchIn() {
if (DateTimeOut is null and now() < tomorrow()) { 
    Set DateTimeOut = now() 
    Create new record } 
if (DateTimeOut is null and now() > tomorrow()) {
    Set DateTimeOut = getDefaultEndOfDayFromYesterdafy() 
    Create new record }
}

答案 6 :(得分:0)

当你问:“我需要修改那些拳,但我想确保更改不重叠”解决方案是:(1)修改/添加打孔 - &gt; (2)验证 - &gt; (3)保存与否

一般情况下,如果没有“关闭”没有EndDate的员工,则不应为员工添加打卡。 然后 - &gt;如果所有拳头都“关闭”,您可以添加新的StartDate比任何其他EndDate员工更大 - 但如果发生一天员工忘记盖章(进出),您将不得不在其他人之间添加“新旧” - 所以:您选择员工,设置您的StartDate和EndDate,项目ID和其他 - &gt;而且你在以下情况下检查数据库:

  1. 有StartDates或EndDates 在您的StartDate和。之间的数据库中 EndDate - &gt;重叠(其他打孔 在你的新拳击中开始或结束)

  2. 有StartDates lass比你的 然后StartDate和EndDate变大 你的EndDate - &gt;重叠(你的新 冲头在其他冲头内

  3. SQL中的所有这些查询必须为一名员工完成(一名员工不能同时在多个项目中)

    如果没有出现此错误,您可以安全添加打卡。我是一些伪代码和我的英语的故事。我希望它有用。

答案 7 :(得分:0)

首先,关于您的问题,从架构的角度来解决这个问题的方法是为每一行存储前一个时间。这个技巧设计了ProjectNumber,EmployeeId和DateTimeIn的唯一约束,以及ProjectNumber,EmployeeId和PreviousDateTime到ProjectNumber,EmployeeId,DateTimeOut的外键引用。还应该注意的是,我依赖于Unique约束允许单个null,这在所有数据库系统中都不是真的(当然,我也依赖于数据库系统来遵守检查约束,这在所有数据库系统中都不是这样) )。

Create Table Punches
    (
    PunchId int not null Primary Key
    , ProjectNumber varchar...
    , EmployeeId int not null..
    , DateTimeIn datetime not null
    , DateTimeOut datetime null
    , PreviousDateTimeOut datetime null

    , Unique ( ProjectNumber, EmployeeId, DateTimeIn )
    , Unique ( ProjectNumber, EmployeeId, DateTimeOut )
    , Unique ( ProjectNumber, EmployeeId, PreviousDateTimeOut )

    , Check ( DateTimeIn <= DateTimeOut )
    , Check( PreviousDateTimeOut <= DateTimeIn )

    , Foreign Key ( ProjectNumber, EmployeeId, PreviousDateTimeOut )
        References Punches( ProjectNumber, EmployeeId, DateTimeOut )
    )

这种方法的优点是模式本身可以防止重叠。缺点是插入有点棘手。给定项目的给定员工的第一行将需要为PreviousDateTimeOut使用null,因为我们不会有前一行。其次,这意味着打卡将需要找到之前的日期时间

Insert Punches( ProjectNumber, EmployeeId, DateTimeIn, PreviousDateTimeOut )
Select ProjectNumber, EmployeeId, CURRENT_TIMESTAMP
    , Coalesce(
        (
        Select Max( DateTimeOut )
        From Punches
        Where DateTimeOut Not Null
        )
        , CURRENT_TIMESTAMP )

以上简单解决了重叠的问题。但是,除了通过防止为同一ProjectNumber和Employee和null DateTimeOut插入两行而阻止没有先前打卡的打卡,它不一定能解决被遗忘的问题。应该发生什么可能涉及更复杂的业务规则。