12

标题可能有点混乱,所以请允许我解释一下。我正在使用表格来记录我的工作日志。每天我都会创建一个条目,说明我从什么时间工作到什么时间,并添加一条评论来描述我所做的事情。

然后,我使用查询来比较时间戳,以准确计算出我那天工作了多少小时和分钟。此外,我使用查询来计算我全年工作的小时数和分钟数的总和。那就是我遇到问题的地方。我的查询如下。

SELECT TIME_FORMAT(SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(entry_end_time, entry_start_time)))), '%H:%i') 
AS total FROM entry 
WHERE entry_date BETWEEN '2012-01-01' AND '2012-12-31' AND user_id = 3

默认情况下,MySQL TIME 字段允许 '-838:59:59' 到 '838:59:59' 的时间范围。不过,今年我目前已经记录了 900 多个小时的工作,我希望我的查询结果能够反映这一点。相反,结果是 838:59:59,这是有道理的,因为这是极限。

有什么办法可以解决这个问题,这样查询的结果可以超过 839 小时,还是我必须使用 PHP 之类的东西来遍历整个表并将其全部加起来?如果可能的话,我有点想避免这种情况。

4

6 回答 6

6

我只是检索工作的总秒数,并根据我的应用程序表示层的要求转换为小时/分钟(毕竟,这是一个简单的除以 60 的情况):

<?
  $dbh = new PDO("mysql:dbname=$dbname", $username, $password);
  $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);

  $qry = $dbh->prepare('
    SELECT SUM(TIME_TO_SEC(entry_end_time)-TIME_TO_SEC(entry_start_time))
    FROM   entry 
    WHERE  entry_date BETWEEN :start_date AND :end_date
       AND user_id = :user_id
  ');

  $qry->execute([
    ':start_date' => '2012-01-01',
    ':end_date'   => '2012-12-31',
    ':user_id'    => 3
  ]);

  list ($totalMins, $remngSecs) = gmp_div_qr($qry->fetchColumn(), 60);
  list ($totalHour, $remngMins) = gmp_div_qr($totalMins, 60);

  echo "Worked a total of $totalHour:$remngMins:$remngSecs.";
?>
于 2012-12-05T22:34:46.037 回答
5

看看没有 TIME 限制的timestampdiff 。即类似(未经测试):

SELECT CONCAT(
        TIMESTAMPDIFF(HOURS, entry_end_time, entry_start_time), 
        ":",
        MOD(TIMESTAMPDIFF(MINUTES, entry_end_time, entry_start_time),60)
      )
AS total FROM entry 
WHERE entry_date BETWEEN '2012-01-01' AND '2012-12-31' AND user_id = 3

concats 并不理想,我相信会有更优雅的解决方案。

于 2012-12-05T22:19:52.320 回答
1

一些简单的数学可以解决问题,我硬编码了一个随机的秒数(10000000)

SELECT CONCAT(FLOOR(10000000/3600),':',FLOOR((10000000%3600)/60),':',(10000000%3600)%60)

小提琴

2777:46:40
于 2018-10-11T19:07:20.653 回答
0

单独计算天数就足够了。
这是我使用的串联。

我用一个完全复制/可粘贴的示例进行说明,以方便理解我们达到的限制(TIME 格式的最大值)
捆绑了一个免费的独角兽以简化逗号管理

SELECT 'pq7~' AS unicorn
#######################
##  Expected result  ##
#######################
## Total, formatted as days:hh:mm:ss ##
  ,CONCAT(
    FLOOR(TIMESTAMPDIFF(SECOND, '2017-01-01 09:17:45', '2017-03-07 17:06:24') / 86400)
    , ':'
    , SEC_TO_TIME(TIMESTAMPDIFF(SECOND, '2017-01-01 09:17:45', '2017-03-07 17:06:24') % 86400)
  ) AS Real_expected_result

#########################
## Calculation details ##
#########################
## Extracted days from diff ##
  ,FLOOR(TIMESTAMPDIFF(SECOND, '2017-01-01 09:17:45', '2017-03-07 17:06:24') / 86400) AS Real_days
## Extracted Hours/minutes/seconds from diff ##
  ,SEC_TO_TIME(TIMESTAMPDIFF(SECOND, '2017-01-01 09:17:45', '2017-03-07 17:06:24') % 86400) AS Real_hours_minutes_seconds

###################################
## Demo of wrong values returned ##
###################################
  ,TIMESTAMPDIFF(SECOND, '2017-01-01 09:17:45', '2017-03-07 17:06:24') AS Real_seconds_diff

## WRONG value returned. 5.64M is truncated to 3.02 ! ##
  ,TIME_TO_SEC(SEC_TO_TIME(5644119)) AS WRONG_result

## Result is effectively limited to 838h59m59s ##
  ,SEC_TO_TIME(TIMESTAMPDIFF(SECOND, '2017-01-01 09:17:45', '2017-03-07 17:06:24')) AS Limit_hit

## Lights on said limit ##
  ,SEC_TO_TIME( 3020398) AS Limit_value_check1
  ,SEC_TO_TIME( 3020400) AS Limit_value_check2
于 2017-10-09T14:50:45.867 回答
-1

首先计算天差,然后将其乘以 24*60*60 以将其转换为秒,然后将其添加到 time_to_sec 值结果

DATEDIFF(start_date,end_date)*24*60*60 + TIME_TO_SEC(TIMEDIFF(TIME(start_date),TIME(end_date))) 
AS sec_diff

有关更多详细信息,请查看codebucket-Surpassing time_to_sec() 函数最大限制

于 2013-09-03T08:48:28.717 回答
-1
select  concat(truncate(sum(time_to_sec(TIMEDIFF(hora_fim, hora_ini)))/3600,0), ':', 
TIME_FORMAT(sec_to_time(sum(time_to_sec(TIMEDIFF(hora_fim, hora_ini))) - truncate(sum(time_to_sec(TIMEDIFF(hora_fim, hora_ini)))/3600,0)*3600), '%i:%s'))
as hms from  tb_XXXXXX
于 2017-07-05T20:12:23.683 回答