将 zk 日志签入和签出插入数据库中的一行

问题描述

我正在使用 zkteco-sdk-php 从 ZK 考勤设备检索数据。

结果是这样的

UID ID 姓名 状态 日期 时间 类型
55 275 雇佣 1 指纹 19-06-2021 08:14:16 签到
55 275 雇佣 1 指纹 19-06-2021 11:15:20 退房

*而且所有的数据都不是按用户排序的,而是按第一个指纹考勤排序的,所以日志会随着不同用户和不同类型的考勤而混淆

我想将检索到的数据插入数据库,问题是正在检索数据 每个日志(签入或签出)作为单行 我想在同一天插入(签入&签出同一行中的同一用户

这就是我的目标

ID 用户 ID 签到 退房
55 275 19-06-2021 08:14:16 19-06-2021 11:15:20

这是从zk中检索数据的代码

                    $attendance = $zk->getAttendance();
                    if (count($attendance) > 0) {
                        $attendance = array_reverse($attendance,true);
                        sleep(1);
                        foreach ($attendance as $attItem) {
                            ?>
                            <tr>
                                <td><?PHP echo($attItem['uid']); ?></td>
                                <td><?PHP echo($attItem['id']); ?></td>
                                <td><?PHP echo(isset($users[$attItem['id']]) ? $users[$attItem['id']]['name'] : $attItem['id']); ?></td>
                                <td><?PHP echo(ZK\Util::getAttState($attItem['state'])); ?></td>
                                <td><?PHP echo(date("d-m-Y",strtotime($attItem['timestamp']))); ?></td>
                                <td><?PHP echo(date("H:i:s",strtotime($attItem['timestamp']))); ?></td>
                                <td><?PHP echo(ZK\Util::getAttType($attItem['type'])); ?></td>
                            </tr>



解决方法

MySQL:

SELECT
   t1.ID,t1.UserID,ADDTIME(CONVERT(t1.`date`,DATETIME),t1.`time`) as "Check-in",ADDTIME(CONVERT(t2.`date`,t2.`time`) as "Check-out"
FROM table t1
LEFT JOIN table t2 ON t2.ID=t1.ID 
                  and t2.UserID=t1.UserID
                  and t2.Type = 'Check-out'
WHERE 
   ID = 55
   and UserID = 275
   and Type = 'Check-in'

注意:您需要用正确的表名替换 table

在很多地方都可以找到有关如何在 PHP 中使用此 SQL 查询的不同示例,例如:Google: how to query MySQL from PHP

,

您应该“按原样”存储日志 - 将行分开以进行签入和签出,并在选择时通过 UUIDID 连接两行:

select 
    log_in.uuid,log_in.id,log_in.name,log_in.state,log_in.event_time as log_in_time,log_out.event_time as log_out_time
from zk_log log_in
join zk_log log_out on log_in.uuid = log_out.uuid and log_in.id = log_out.id
where log_in.event_type = 'check-in' and log_out.event_type = 'check-out';
,

我认为可以这样实现:

SELECT UID,ID,CONCAT(date,' ',MIN(time)) AS Check_in,MAX(time)) AS Check_out
FROM attendance
GROUP BY date,UID,ID;

但我必须指出,您示例中的 date 数据不是标准的 MySQL DATE 数据类型,并且您要插入的目标表是否具有如下结构:

destination_table 
(UID INT,ID INT,Check_in DATETIME,<--- this datatype
Check_out DATETIME); <---

插入不会成功,会返回错误:

日期时间值不正确:第 1 行的“Check_in”列的“19-06-2021 08:14:16”

否则,如果 destination_table 数据类型为 VARCHAR(),则插入不会有问题。但是,我强烈建议在目标表上至少使用标准格式。因此,如果源表确实将日期存储为 VARCHAR() 并且目标表使用的是 DATETIME 数据类型,则您将需要 STR_TO_DATE():

INSERT INTO destination_table
SELECT UID,CONCAT(STR_TO_DATE(date,'%d-%m-%Y'),ID;

Here's a demo fiddle