如何将记录选择到单个记录中以确定TIME差异

问题描述 投票:2回答:2

我有一个第三方时钟应用程序,我们用它来跟踪我们员工的动作。它运行在MariaDB上,但它非常混乱(imo)。前端是基于窗口的,所有处理都在那里进行。问题是我想提取一些实时报告数据。

所有计时活动都保存到一个表中。见下面的示例。

INDX    _DATE_      _TIME_      SURNAME WIEGANDID       ZKINOUT
51      2018/09/03  5:52:04     Thakadu 000000000000AE  0
198     2018/09/03  14:04:29    Thakadu 000000000000AE  1
309     2018/09/03  21:54:06    Mabeo   000000000000BA  0
370     2018/09/04  5:47:20     Thakadu 000000000000AE  0
401     2018/09/04  6:00:09     Mabeo   000000000000BA  1
557     2018/09/04  14:04:57    Thakadu 000000000000AE  1
691     2018/09/04  21:53:33    Mabeo   000000000000BA  0
748     2018/09/05  5:47:20     Thakadu 000000000000AE  0
780     2018/09/05  6:00:34     Mabeo   000000000000BA  1
946     2018/09/05  14:05:32    Thakadu 000000000000AE  1
1089    2018/09/05  21:49:48    Mabeo   000000000000BA  0
1144    2018/09/06  5:50:41     Thakadu 000000000000AE  0
1174    2018/09/06  6:00:16     Mabeo   000000000000BA  1
1328    2018/09/06  14:09:28    Thakadu 000000000000AE  1
1482    2018/09/06  21:50:32    Mabeo   000000000000BA  0
1568    2018/09/07  5:58:48     Thakadu 000000000000AE  0
1555    2018/09/07  6:01:01     Mabeo   000000000000BA  1
1812    2018/09/07  14:05:47    Thakadu 000000000000AE  1
1845    2018/09/07  21:51:31    Mabeo   000000000000BA  0

Mabeo第二天早上从22:00:00到06:00:00工作的挑战来了。此外,有时工作人员由于某种原因没有退出时间,系统会自动将其记录下来,而不记录时间。

我希望看到的结果看起来像这样。

DATE_IN     TIME_IN    DATE_OUT    TIME_OUT    SURNAME    WIEGANDID
2018/09/03  05:52:04   2018/09/03  14:04:29    Thakadu    000000000000AE    
2018/09/03  21:54:06   2018/09/04  06:00:09    Mabeo      000000000000BA
2018/09/04  05:47:20   2018/09/04  14:04:57    Thakadu    000000000000AE
2018/09/04  21:53:33   2018/09/05  06:00:16    Mabeo      000000000000BA

通过这种方式,我可以计算出每个人在一段时间内获得的实际时间。

我使用GROUP BY和CASE取得了一些成功,但问题在于员工工作夜班。

任何帮助,将不胜感激。

--------------------------------- UPDATE ---------------- ---------------

好的,非常感谢所有贡献的人。我几乎得到了答案,除了那里还没有100%。我已经使用了@ rf1234建议的以下代码,谢谢你的回答。

SELECT COALESCE (a.DATE_IN, b.DATE_IN)                  AS DATE_IN,
       SUBSTR(COALESCE (a.TIME_IN, b.TIME_IN), 1, 8)    AS TIME_IN,
       CASE WHEN ( b.DATE_TIME_OUT > a.DATE_TIME_IN ) THEN COALESCE (a.DATE_OUT, 
            b.DATE_OUT) ELSE '' END                     AS DATE_OUT,
       CASE WHEN ( b.DATE_TIME_OUT > a.DATE_TIME_IN ) THEN 
            SUBSTR(COALESCE (a.TIME_OUT, b.TIME_OUT), 1, 8) ELSE '' END
                                                        AS TIME_OUT,
       COALESCE (a.SURNAME, b.SURNAME)                  AS SURNAME,
       COALESCE (a.WIEGANDID, b.WIEGANDID)              AS WIEGANDID,
       CASE WHEN ( b.DATE_TIME_OUT > a.DATE_TIME_IN ) THEN
            TIMESTAMPDIFF(SECOND, a.DATE_TIME_IN, b.DATE_TIME_OUT) / 3600 ELSE '' END
                                                        AS HOURS_WORKED
FROM (
    SELECT  _DATE_  AS  DATE_IN,
            _TIME_  AS  TIME_IN,
            NULL    AS  DATE_OUT,
            NULL    AS  TIME_OUT,
            SURNAME,
            WIEGANDID,
            CONCAT( _DATE_, ' ', _TIME_ ) AS DATE_TIME_IN
          FROM _2018_09
         WHERE ZKINOUT = 0 AND SURNAME = 'MABEO'
         GROUP BY WIEGANDID, _DATE_ )   AS   a,
    (

    SELECT  NULL    AS  DATE_IN,
        NULL    AS  TIME_IN,
        _DATE_  AS  DATE_OUT,
        _TIME_  AS  TIME_OUT,
        SURNAME,
        WIEGANDID,
        CONCAT( _DATE_, ' ', _TIME_ ) AS DATE_TIME_OUT
      FROM _2018_09
     WHERE ZKINOUT = 1 AND SURNAME = 'MABEO'
     GROUP BY WIEGANDID, _DATE_)   AS   b
WHERE a.WIEGANDID = b.WIEGANDID
ORDER BY 1, 2, 3, 4

我现在修改了代码,只选择了一名员工。我得到的结果几乎是我想要的,除了它似乎将表a的每个记录连接到表b的每个记录?下面是结果样本的图像。

Sample of result set

mysql mariadb mariasql
2个回答
0
投票

正如ArSuKa大师所说,通过重新设计数据库,你当然可以轻松实现这一目标。但是,让我们看看我们是否可以用你拥有的东西来获得你的结果。我们还通过在临时表中区分两个时间戳来计算班次已经结束的工作小时数(浮点数)。使用临时DATE_TIME列解决了员工工作夜班的问题。无论换班是否在不同的一天结束,计算都是正确的。

SELECT COALESCE (a.DATE_IN, b.DATE_IN)                  AS DATE_IN,
       SUBSTR(COALESCE (a.TIME_IN, b.TIME_IN), 1, 8)    AS TIME_IN,
       CASE WHEN ( b.DATE_TIME_OUT > a.DATE_TIME_IN ) THEN COALESCE (a.DATE_OUT, 
            b.DATE_OUT) ELSE '' END                     AS DATE_OUT,
       CASE WHEN ( b.DATE_TIME_OUT > a.DATE_TIME_IN ) THEN 
            SUBSTR(COALESCE (a.TIME_OUT, b.TIME_OUT), 1, 8) ELSE '' END
                                                        AS TIME_OUT,
       COALESCE (a.SURNAME, b.SURNAME)                  AS SURNAME,
       COALESCE (a.WIEGANDID, b.WIEGANDID)              AS WIEGANDID,
       CASE WHEN ( b.DATE_TIME_OUT > a.DATE_TIME_IN ) THEN
            TIMESTAMPDIFF(SECOND, a.DATE_TIME_IN, b.DATE_TIME_OUT) / 3600 ELSE '' END
                                                        AS HOURS_WORKED
FROM (
    SELECT  _DATE_  AS  DATE_IN,
            _TIME_  AS  TIME_IN, 
            NULL    AS  DATE_OUT,
            NULL    AS  TIME_OUT,
            SURNAME,
            WIEGANDID,
            CONCAT( _DATE_, ' ', _TIME_ ) AS DATE_TIME_IN
       FROM test 
      WHERE ZKINOUT = 0 )   AS   a,
    (
    SELECT  NULL    AS  DATE_IN,
            NULL    AS  TIME_IN, 
            _DATE_  AS  DATE_OUT,
            _TIME_  AS  TIME_OUT,
            SURNAME,
            WIEGANDID,
            CONCAT( _DATE_, ' ', _TIME_ ) AS DATE_TIME_OUT
       FROM test
      WHERE ZKINOUT = 1 )   AS   b
WHERE a.WIEGANDID = b.WIEGANDID  
HAVING HOURS_WORKED < 15 AND HOURS_WORKED <> ''
ORDER BY 1, 2, 3, 4

这看起来有点复杂,它执行以下操作。创建两个临时表a和b。这些是()中的SELECT语句。一个临时表包含登录记录,另一个临时表包含注销记录。相应的“缺失”字段设置为NULL。

然后可以使用WIEGANDID将这些表相互连接起来。 COALESCE确保过滤掉空值,并替换为包含正确值的其他临时表中的值。检查DATE_TIME_OUT是否大于DATE_TIME_IN,确保如果相应的工作人员尚未注销,则DATE_OUT和TIME_OUT保持为空。

我在结果表中添加了一个新列:HOURS_WORKED。它包含作为浮点数的小时数。在结果集中忽略尚未结束的移位(HOURS_WORKED <>'')。为了消除重复并避免过多的复杂性,我们过滤掉了HOURS_WORKED> 15的结果集记录,因为实际上并没有这种情况发生,并且在两个班次之间通常有足够的时间我们没有捕获两个短班。不是一般解决方案,而是适用于此特定应用的解决方案。

您可以在CREATE VIEW语句中使用上述语句。然后,您可以使用视图而不是原始表,这将有助于降低复杂性。

下图显示了基于所有样本记录的上述查询结果。 enter image description here


0
投票

我上周才创建了一个应用程序,用于监控我的员工的punchIN和PunchOUT时间,以监控他们的出勤情况,从而将他们的假期,半天等用于进一步分析数据。

看到您提供的数据,我建议使我的分析应用程序非常简单。使用punchIN和PunchOUT的Timestamp数据类型,此步骤不仅会合并您现有的列,还会使您的工作无障碍。

使用IN和OUT时间,您可以计算“工作时间”(简单算术!)。您可以添加标记以查看某人是否在夜间工作(使用BETWEEN功能)等。即用型简单功能将带路!

如果您需要任何帮助,请告诉我...... !!

© www.soinside.com 2019 - 2024. All rights reserved.