我将此表命名为 time_track :
+----+--------+---------------------+---------+
| id | emplid | ctimestamp | eventid |
+----+--------+---------------------+---------+
| 1 | 13 | 2016-06-02 03:41:41 | 1 |
+----+--------+---------------------+---------+
| 2 | 13 | 2016-06-02 09:04:49 | 2 |
+----+--------+---------------------+---------+
| 3 | 13 | 2016-06-02 10:03:13 | 1 |
+----+--------+---------------------+---------+
| 4 | 13 | 2016-06-02 13:21:23 | 2 |
+----+--------+---------------------+---------+
其中eventid 1 = Start work
和eventid 2 = Stop work
。
我如何计算任何一天的小时数,考虑到工作时间是所有的偶数1和2之间的总小时数 - WHERE emplid = 13 AND Year(ctimestamp) = 2016 and Month(ctimestamp) = 06 and Day(ctimestamp) = 02
答案 0 :(得分:4)
您也可以使用PHP(而不是SQL):
<?php
$data = array( array( "1","2016-06-02 03:41:41" ),
array( "2","2016-06-02 09:04:49" ),
array( "1","2016-06-02 10:03:13" ),
array( "2","2016-06-02 13:21:23" )
);
$hours = 0;
foreach ( $data as $row ) // PROCESS ALL ROWS FROM QUERY.
{ if ( $row[ 0 ] == "1" ) // IF CURRENT ROW IS START TIME
$start = strtotime( $row[ 1 ] );
else { $stop = strtotime( $row[ 1 ] ); // STOP TIME. CALCULATE.
$hours += ( $stop - $start ) / 3600;
}
}
echo $hours; // 8.6883333333333.
?>
您可以对结果进行舍入。
将以前的代码复制粘贴到文件中,将其另存为.PHP并在浏览器中打开。随意更改样本数据。
编辑:调用函数计算所有小时数更容易:
<?php
function total_hours ( $data )
{ $hours = 0;
foreach ( $data as $row )
if ( $row[ "eventid" ] == "1" )
$start = strtotime( $row[ "ctimestamp" ] );
else { $stop = strtotime( $row[ "ctimestamp" ] );
$hours += ( $stop - $start ) / 3600;
}
return $hours;
}
$sample_data = array( array( "id" => 1,
"emplid" => 13,
"ctimestamp" => "2016-06-02 03:41:41",
"eventid" => 1 ),
array( "id" => 2,
"emplid" => 13,
"ctimestamp" => "2016-06-02 09:04:49",
"eventid" => 2 ),
array( "id" => 3,
"emplid" => 13,
"ctimestamp" => "2016-06-02 10:03:13",
"eventid" => 1 ),
array( "id" => 4,
"emplid" => 13,
"ctimestamp" => "2016-06-02 13:21:23",
"eventid" => 2 )
);
echo total_hours( $sample_data ); // 8.6883333333333.
?>
使用您从查询中获取的sql-result调用此函数作为参数(并将foreach
替换为while ( $row = mysqli_fetch_array
)。
答案 1 :(得分:3)
与以下只有SQL的答案不同,它可以高效地结合SQL和PHP以提高可读性和性能。此外,PHP将允许您编写如何处理丢失或双重数据等异常的代码。
<?php
// Generate test data like it would be returned by a PDO::fetchAll(PDO:::FETCH_ASSOC) with
// SELECT * FROM time_track
// WHERE emplid = 13 AND Year(ctimestamp) = 2016 and Month(ctimestamp) = 06 and Day(ctimestamp) = 02
// ORDER BY ctimestamp
$logs[] = ['ctimestamp'=>'2016-06-02 03:41:41', 'eventid'=>1];
$logs[] = ['ctimestamp'=>'2016-06-02 09:04:49', 'eventid'=>2];
$logs[] = ['ctimestamp'=>'2016-06-02 10:03:13', 'eventid'=>1];
$logs[] = ['ctimestamp'=>'2016-06-02 13:21:23', 'eventid'=>2];
// Compute working time
$worktime = 0; // in seconds
foreach ($logs as $log) {
if ($log['eventid'] == 1) { // start work
$startWork = $log['ctimestamp'];
} else { // end work
$endWork = $log['ctimestamp'];
$worktime += strtotime($endWork) - strtotime($startWork);
}
}
echo gmdate('H:i', $worktime); // seconds to hours:minutes
?>
正在运行代码:http://phpfiddle.org/main/code/jx8h-ztuy
以下是对上述代码的测试改进,包括数据库访问和循环
由于您表明性能至关重要,因此您可能需要使用PDO::prepare()
<pre>
<?php
class TimeLog {
private $pdo;
private $pdoStatement;
// constructor: connect to database and prepare statement
function __construct(){
// adapt following constructor to your database configuartion
$this->pdo = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8mb4', 'username', 'password');
$this->pdoStatement = $this->pdo->prepare(
'SELECT * FROM time_track
WHERE emplid = :emplid
AND DATE(ctimestamp) = :cdatestamp
ORDER BY ctimestamp
');
}
// compute workTime for given employee and date
function workTime($emplid, $cdatestamp) {
// fetch from database, executing prepared statement
$this->pdoStatement->execute([':emplid'=>$emplid, ':cdatestamp'=>$cdatestamp]);
$logs = $this->pdoStatement->fetchAll(PDO::FETCH_ASSOC);
// compute working time
$worktime = 0; // in seconds
foreach ($logs as $log) {
if ($log['eventid'] == 1) { // start work
$startWork = $log['ctimestamp'];
} else { // end work
$endWork = $log['ctimestamp'];
$worktime += strtotime($endWork) - strtotime($startWork);
}
}
return gmdate('H:i', $worktime); // convert seconds to hours:minutes
}
}
$timeLog = new Timelog(); // invoke constructor once
$emplid = 13; // example
// echo registration of last seven days
for ($date = strtotime('-7 days'); $date <= time(); $date += 24 * 3600) {
// convert $date to YYYY-MM-DD format
$cdatestamp = date('Y-m-d', $date);
// execute one SQL statement and return computed worktime
$workTime = $timeLog->workTime($emplid, $cdatestamp);
// show result
echo $cdatestamp, "\t", $workTime, "\n";
}
?>
答案 2 :(得分:2)
你必须在子句中自己加入你自己的表,并获得大于eventid = 1的eventid = 2的min并计算这两个记录之间的差异。在外部查询中,您总结了eventid = 1时间戳的日期差异:
select date(t3.ctimestamp), t3.emplid, sum(diff) / 60 as hours_worked
from
(select t1.id, t1.ctimestamp, t1.emplid, min(t2.ctimestamp) as mintime, timestampdiff(minute,min(t2.ctimestamp), t1.ctimestamp) as diff
from yourtable t1
inner join yourtable t2 on t1.ctimestamp<t2.ctimestamp
where t1.eventid=1
and t2.eventid=2
and t1.emplid=13
and t2.emplid=13
and date(t1.ctimestamp)='2016-06-02' --may have checked out the next day, I do not know how you want to handle that
group by t1.id, t1.ctimestamp, t1.emplid) t3
group by date(t3.ctimestamp)
在实时环境中,我不会在没有间隙的id列上建立解决方案,即使它是自动增量列。通常有差距。如果您有孤儿签入或签出事件,您还需要决定会发生什么。我的代码假设每次签入都有相应的签出。
答案 3 :(得分:1)
您可以尝试这样的事情
如果您需要进一步分离数据,也可以按年份和月份进行分组。
select day(ctimestamp) as Day, hour(ctimestamp) as Hour, count(*) as Count
from MyTable
where ctimestamp between :date1 and :date2
group by day(ctimestamp), hour(ctimestamp)
答案 4 :(得分:1)
您需要计算事件1和事件2的时间戳之间的差异。这假设对于任何给定的日期,每个empl_id只有2个事件,结账时间在同一天内(例如,隔夜时间不会显示在此查询中)。它不是一个非常强大的解决方案,但我不确定您的数据的完整性以及您需要处理的边缘情况。
SELECT TIMEDIFF(t1.c_timestamp, t2.c_timestamp) / 3600 AS hourDiff
FROM time_track t1
INNER JOIN time_track t2
ON (t2.id > t1.id AND t2.event_id = 2 AND t1.empl_id = t2.empl_id AND DAY(t2.c_timestamp) = DAY(t1.c_timestamp) AND MONTH(t2.c_timestamp) = MONTH(t1.c_timestamp) AND YEAR(t2.c_timestamp) = YEAR(t1.c_timestamp))
WHERE t1.event_id = 1 AND t1.empl_id = 13 AND Year(t1.c_timestamp) = 2016 and Month(t1.c_timestamp) = 6 and Day(t1.c_timestamp) = 2
答案 5 :(得分:0)
SELECT UNIX_TIMESTAMP(&#39; 2010-11-29 13:16:55&#39;) - UNIX_TIMESTAMP(&#39; 2010-11-29 13:13:55&#39;)作为输出
$http.get("http://www.yahoo.com")
.then(function (response) {
alert("Search Results: " + response);
}, function(error) {
alert("Could not get to Yahoo");
});
= [...在此处使用查询...]
$entry_time
= [...在此处使用查询...]
$ query =&#34; $exit_time
&#34;。$ entry_time。&#34; SELECT UNIX_TIMESTAMP('
&#34;。') - UNIX_TIMESTAMP('
。&#34; $exit_time
&#34 ;;
答案 6 :(得分:-1)
QUERY:
SELECT DATEDIFF('2010-10-08 18:23:13', '2010-09-21 21:40:36') AS days;
$ time_entry = [...] //查找查询并保存输出到此变量
$ time exit = [...] //查找查询并保存输出到此变量
$ query =&#34;
SELECT DATEDIFF('
&#34;。 time_entry。&#34;', '
&#34; .time_exit。&#34;') AS days;
&#34;