Sum SQL时间戳

时间:2016-06-20 20:20:54

标签: mysql sql

如何通过'id = 1'进行总和搜索并将其小时数加起来。 第一行将及时到达,下一行将是他们的外出时间。

下面应该加起来为5:43:29

id, ts
1,2016-06-20 04:25:32
3,2016-06-20 07:40:09
1,2016-06-20 09:37:46
3,2016-06-20 14:40:57
1,2016-06-20 15:12:14
1,2016-06-20 15:43:29
2,2016-06-20 15:47:01
2,2016-06-20 17:47:03

4 个答案:

答案 0 :(得分:0)

哦,小伙子,这很有趣:

SELECT SEC_TO_TIME(
    SUM(UNIX_TIMESTAMP(
        (SELECT ts FROM example_table e2 WHERE id = ranked.id AND ts > ranked.ts ORDER BY id, ts LIMIT 1)
    )-UNIX_TIMESTAMP(ts))
)
FROM ( 
    SELECT 
        @row := @row +1 AS rownum, id, ts
    FROM ( 
        SELECT @row :=0) r, example_table
    WHERE id = 1
    ORDER BY id ASC, ts ASC
    ) ranked 
WHERE ranked.rownum % 2 = 1

首先我们获取所有奇数行:1,3,5,7和soforth。接下来,我们使用子查询来获取与该行匹配的下一个时间戳(打卡时间),并获得差异(以秒为单位)。 Sum将总计秒数,sec_to_time会将其转换为友好的可读格式。

答案 1 :(得分:0)

您可以使用用户定义的变量添加行号。奇数行表示开始时间,当它是if(r%2=0,1,-1)的开始时间时乘以-1,并将它们相加:

select sec_to_time(sum(time_to_sec(ts)*if(r%2=0,1,-1)))
from (
  select @row:=@row+1 r, a.*
  from Table1 a
  join (select @row:=0) b
  where a.id = 1) a;

答案 2 :(得分:0)

这里我的回答是一个样本

使用这样的SQL:

SELECT
  t_from.id,
  SEC_TO_TIME(SUM(TIME_TO_SEC( TIMEDIFF(
    ( SELECT ts 
      FROM t t_to
      WHERE
        t_to.ts > t_from.ts_from
      AND
        t_to.id = t_from.id
      ORDER BY t_to.id,t_to.ts
      LIMIT 1
    )
    ,  t_from.ts_from
   )))) AS ts_diff
FROM (
  SELECT @nr:=((@nr+1) %2) AS nr,t.id,t.ts AS ts_from
  FROM t
  CROSS JOIN ( SELECT @nr:=0) AS parameter
  ORDER BY id
) AS t_from
WHERE nr =1
GROUP BY t_from.id;

我的表

MariaDB [yourSchema]> select * from t;
+----+---------------------+
| id | ts                  |
+----+---------------------+
|  1 | 2016-06-20 04:25:32 |
|  3 | 2016-06-20 07:40:09 |
|  1 | 2016-06-20 09:37:46 |
|  3 | 2016-06-20 14:40:57 |
|  1 | 2016-06-20 15:12:14 |
|  1 | 2016-06-20 15:43:29 |
|  2 | 2016-06-20 15:47:01 |
|  2 | 2016-06-20 17:47:03 |
+----+---------------------+
8 rows in set (0.00 sec)

转换为开始结束时间

MariaDB [yourSchema]> SELECT
    ->   t_from.id
    ->   , t_from.ts_from,
    ->   ( SELECT ts
    ->       FROM t t_to
    ->       WHERE
    ->         t_to.ts > t_from.ts_from
    ->       AND
    ->         t_to.id = t_from.id
    ->       ORDER BY t_to.id,t_to.ts
    ->       LIMIT 1
    ->     )  AS ts_to
    -> FROM (
    ->   SELECT @nr:=((@nr+1) %2) AS nr,t.id,t.ts AS ts_from
    ->   FROM t
    ->   CROSS JOIN ( SELECT @nr:=0) AS parameter
    ->   ORDER BY id
    -> ) AS t_from
    -> WHERE nr =1;
+----+---------------------+---------------------+
| id | ts_from             | ts_to               |
+----+---------------------+---------------------+
|  1 | 2016-06-20 04:25:32 | 2016-06-20 09:37:46 |
|  1 | 2016-06-20 15:12:14 | 2016-06-20 15:43:29 |
|  2 | 2016-06-20 15:47:01 | 2016-06-20 17:47:03 |
|  3 | 2016-06-20 07:40:09 | 2016-06-20 14:40:57 |
+----+---------------------+---------------------+
4 rows in set (0.00 sec)

MariaDB [yourSchema]>

按ID分享差异和分组

MariaDB [yourSchema]> SELECT
    ->   t_from.id,
    ->   SEC_TO_TIME(SUM(TIME_TO_SEC( TIMEDIFF(
    ->     ( SELECT ts
    ->       FROM t t_to
    ->       WHERE
    ->         t_to.ts > t_from.ts_from
    ->       AND
    ->         t_to.id = t_from.id
    ->       ORDER BY t_to.id,t_to.ts
    ->       LIMIT 1
    ->     )
    ->     ,  t_from.ts_from
    ->    )))) AS ts_diff
    -> FROM (
    ->   SELECT @nr:=((@nr+1) %2) AS nr,t.id,t.ts AS ts_from
    ->   FROM t
    ->   CROSS JOIN ( SELECT @nr:=0) AS parameter
    ->   ORDER BY id
    -> ) AS t_from
    -> WHERE nr =1
    -> GROUP BY t_from.id;
+----+----------+
| id | ts_diff  |
+----+----------+
|  1 | 05:43:29 |
|  2 | 02:00:02 |
|  3 | 07:00:48 |
+----+----------+
3 rows in set (0.00 sec)

MariaDB [yourSchema]>

答案 3 :(得分:0)

自己加入表并搜索下一个时间戳:

select t1.id,
    t1.ts as ts_from,
    min(t2.ts) as ts_to,
    timediff(min(t2.ts), t1.ts) as uptime
from uptime t1
join uptime t2
    on  t2.id = t1.id
    and t2.ts > t1.ts
where t1.id = 1
group by t1.id, t1.ts

结果:

| id |             ts_from |               ts_to |   uptime |
|----|---------------------|---------------------|----------|
|  1 | 2016-06-20 04:25:32 | 2016-06-20 09:37:46 | 05:12:14 |
|  1 | 2016-06-20 09:37:46 | 2016-06-20 15:12:14 | 05:34:28 |
|  1 | 2016-06-20 15:12:14 | 2016-06-20 15:43:29 | 00:31:15 |

Demo

您需要id, ts上的索引。

ALTER TABLE `uptime` ADD INDEX `id_ts` (`id`, `ts`);

<强>更新

在再次阅读你的问题后,我想我得到了你所追求的。您可以在子查询中使用obove查询,在偶数行和奇数行之间切换会话变量以及条件SUM:

select sec_to_time(sum(
    case when @switch := 1 - @switch then time_to_sec(sub.uptime) end
)) as uptime
from (
    select timediff(min(t2.ts), t1.ts) as uptime
    from uptime t1
    join uptime t2
        on  t2.id = t1.id
        and t2.ts > t1.ts
    where t1.id = 1
    group by t1.id, t1.ts
    order by t1.ts
) sub
join (select @switch := 0) init_switch

Demo