web-dev-qa-db-ja.com

MySQL:グループでTIMEDIFF()をSUM()する方法は?

したがって、次のような結果のセットがあります。

_SELECT User_ID, StartTime, EndTime, TIMEDIFF(EndTime, StartTime) AS TimeDiff
FROM MyTable

------------------------------------------------------------------
| User_ID |       StartTime     |         EndTime     | TimeDiff |
------------------------------------------------------------------
|    1    | 2010-11-05 08:00:00 | 2010-11-05 09:00:00 | 01:00:00 |
------------------------------------------------------------------
|    1    | 2010-11-05 09:00:00 | 2010-11-05 10:00:00 | 01:00:00 |
------------------------------------------------------------------
|    2    | 2010-11-05 06:30:00 | 2010-11-05 07:00:00 | 00:30:00 |
------------------------------------------------------------------
|    2    | 2010-11-05 07:00:00 | 2010-11-05 09:00:00 | 02:00:00 |
------------------------------------------------------------------
|    2    | 2010-11-05 09:00:00 | 2010-11-05 10:00:00 | 01:00:00 |
------------------------------------------------------------------
_

次に、結果を_User_ID_およびSUM()TimeDiffでグループ化する必要があります。 _GROUP BY_句を追加した場合、TimeDiffはSUM()されません(そして、そうなるとは思いませんでした)。各ユーザーのTimeDiffをSUM()するにはどうすればよいですか?

18
Andrew

使用する:

  SELECT t.user_id,       
         SEC_TO_TIME(SUM(TIME_TO_SEC(t.endtime) - TIME_TO_SEC(t.starttime))) AS timediff
    FROM MYTABLE t
GROUP BY t.user_id

手順:

  1. TIME_TO_SEC を使用して、数学演算のTIMEを秒に変換します
  2. 差を合計する
  3. SEC_TO_TIME を使用して、秒をTIMEに戻します

サンプルデータに基づいて、私はちょうど提案したでしょう:

  SELECT t.user_id,       
         TIMEDIFF(MIN(t.startdate), MAX(t.enddate)) AS timediff
    FROM MYTABLE t
GROUP BY t.user_id   

注:datetimeを使用している場合、このコードにはバグがあります。 TIME_TO_SECは時間セクションのみを変換するため、時計が深夜を過ぎた場合は大きなマイナスになります。代わりにUNIX_TIMESTAMPを使用して合計を行います。また、SEC_TO_TIMEは、3020399秒を超える値で最大になります。 SELECT TIME_TO_SEC(SEC_TO_TIME(3020400));この値が838:59:59になっている場合は、最大値に達しており、時間を表示するには3600で割る必要があります。

37
OMG Ponies

AFAIK、唯一のオプションは、UNIX_TIMESTAMPsにキャストし、整数計算を実行して、日付のないTIME列をランダムな日付(2000-01-01を選択)に置き換えることです。

SELECT TIMEDIFF(
    DATE_ADD('2000-01-01 00:00:00',
       INTERVAL 
       SUM(UNIX_TIMESTAMP(CONCAT('2000-01-01 ',TimeDiff)) - UNIX_TIMESTAMP('2000-01-01 00:00:00')
       SECOND),
    '2000-01-01 00:00:00')
FROM MyTable;

seem TIME列はSUMできますが、実際には、時間の指定に従わない厄介な整数または浮動小数点数にキャストされます(60分を超える合計で試してください。あなたは私が何を意味するかを見るでしょう)。


SUM時間列ができると主張する人のために:

mysql> create table timetest(a TIME);
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO timetest VALUES ('02:00'),('03:00');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT SUM(a) FROM timetest;
+--------+
| SUM(a) |
+--------+
|  50000 |
+--------+
1 row in set (0.00 sec)

mysql> SELECT TIME(SUM(a)) FROM timetest;
+--------------+
| TIME(SUM(a)) |
+--------------+
| 05:00:00     |
+--------------+
1 row in set (0.00 sec)

mysql> -- seems ok, but wait
mysql> INSERT INTO timetest VALUES ('02:30');
Query OK, 1 row affected (0.01 sec)

mysql> SELECT TIME(SUM(a)) FROM timetest;
+--------------+
| TIME(SUM(a)) |
+--------------+
| 07:30:00     |
+--------------+
1 row in set (0.00 sec)

mysql> -- and now, oh ye unbelievers:
mysql> INSERT INTO timetest VALUES ('01:40');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT TIME(SUM(a)) FROM timetest;
+--------------+
| TIME(SUM(a)) |
+--------------+
| NULL         |
+--------------+
1 row in set, 1 warning (0.00 sec)

mysql> -- why is that? because it uses integer arithmetic, not time - arithmetic:
mysql> SELECT SUM(a) FROM timetest;
+--------+
| SUM(a) |
+--------+
|  87000 |
+--------+
1 row in set (0.00 sec)

mysql> -- that cannot be cast to time
2
Wrikken

それはあなたのために働きますか?

SELECT User_ID, TIME(SUM(TIMEDIFF(EndTime, StartTime))) AS TimeDiff
FROM MyTable GROUP BY User_ID

1
a1ex07

これは、時間追跡アプリで私のために働いた。つまり、すべての間隔を秒に変換し、それらを合計して、TIME形式に戻しました。私は初心者ですので、コードの不器用さはご容赦ください。私は常にフィードバックを歓迎します。

CREATE table time_segments(segment_id int not null auto_increment primary key、sign_in DATETIME、sign_out DATETIME、Seconds INT not null、Display TIME not null、user_id INT);

更新time_segments SET Seconds = TIME_TO_SEC(-TIMEDIFF(sign_insign_out));

更新time_segments SET Display = SEC_TO_TIME(Seconds);

INSERT INTO time_segments(sign_in、sign_out、user_id)VALUES( '2019-03-12 14:01:00'、 '2019-03-12 16:45:00'、1)、...;

mysql> select * from time_segments;

| segment_id | sign_in | sign_out |秒|ディスプレイ|

| 1 | 2019-03-12 14:01:00 | 2019-03-12 16:45:00 | 9840 | 02:44:00 |

mysql> SELECT SEC_TO_TIME(SUM(Seconds))AS'Payperiod Hours 'FROM time_segments;

|支払期間時間| + ----------------- + | 49:29:00 |

0
Bobbi Lusic

代わりに TO_SECONDS を使用することをお勧めします:

SELECT t.user_id,       
         SEC_TO_TIME(SUM(TO_SECONDS(t.endtime) - TO_SECONDS(t.starttime))) AS timediff
    FROM MYTABLE t
GROUP BY t.user_id
0
David L

このバグが発生している場合は、TIMESTAMPDIFFを使用して、作成した列の合計を取得することをお勧めします。

select(sum(df.elapse)/60 as diff
from( SELECT c1.start, c1.end, TIMESTAMPDIFF(MINUTE,c1.start,c1.end) as elapse
from c1) df

注意:実際の時間数に非常に近くなりますが、小数点以下数桁ずれている場合があります。詳細については、浮動小数点の丸めを参照してください。

0
Jacky