12

タイトルが少しわかりにくいかもしれませんので、説明させてください。テーブルを使用して作業ログを記録しています。毎日、何時から何時まで働いたかを示すエントリを作成し、自分が何をしたかを説明するコメントを追加します。

次に、クエリを使用してタイムスタンプを比較し、その日に何時間何分働いたかを正確に把握します。さらに、クエリを使用して、1年間に働いた時間と分の合計を計算します。それは私が問題にぶつかっているところです。私の質問は次のとおりです。

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

デフォルトでは、MySQLTIMEフィールドは「-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

時間制限のない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

コンキャットは理想的ではありません。もっとエレガントな解決策があると確信しています。

于 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を確認してください-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 に答える