将带有时间戳的几行合并为带有开始和结束时间戳的一行

时间:2019-11-15 16:23:43

标签: mysql sql

我正在尝试从清单系统后端提取一些SQL报告。

我要报告的表上有一个“操作”列(用于跟踪签入或签出)和一个“时间戳”列。

我正在尝试针对每个具有开始和结束时间的用户/资产组合将其重新格式化为行。

样本数据:

当前:

row_id** user asset out_or_in timestamp 
1        a    4     out       8:40      
2        c    7     out       9:20      
3        a    4     in        9:55      
4        b    4     out       10:00     
5        c    6     out       12:15     
6        a    3     out       12:30     
7        b    4     in        13:10     
8        a    3     in        14:05     
9        b    4     out       15:00     
10       b    4     in        16:20     

所需

row id** user asset out_time in_time 
1        a    4     8:40     9:55    
2        c    7     9:20             
3        b    4     10:00    13:10   
4        c    6     12:15            
5        a    3     12:30    14:05   
6        b    4     15:00    16:20   

**不是必需的,只是为了表的正确性而包含

由于每个用户资产对都可以重复并且需要显示为两行,因此事实变得更加复杂。

有想法吗?

2 个答案:

答案 0 :(得分:0)

MySql 8.0使用row_number()窗口函数来匹配/匹配

select usr,asset
  , max(case event when 'out' then ts end) out_time
  , max(case event when 'in' then ts end) in_time
from (
  select f.*,
      -- first 'out' matches first 'in' and so on
      row_number() over(partition by usr, asset, event order by ts) as grp
  from foo f
  ) t
group by usr, asset, grp
order by out_time 

Db fiddle

答案 1 :(得分:0)

这是对MySql 8的查询,该查询利用MIN OVER来计算in_time。

SELECT q.user, q.asset, q.out_time, q.in_time
FROM
(
    SELECT t.user, t.asset, t.out_or_in, 
     CASE WHEN t.out_or_in = 'out' THEN t.`timestamp` END AS out_time,
     MIN(CASE WHEN t.out_or_in = 'in' THEN t.`timestamp` END) OVER (PARTITION BY t.user, t.asset ORDER BY t.`timestamp` ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING) AS in_time
    FROM YourTable t
) q
WHERE q.out_time IS NOT NULL
ORDER BY q.out_time;

db <>小提琴here

上进行测试

结果:

user    asset   out_time    in_time
a       4       08:40:00    09:55:00
c       7       09:20:00    
b       4       10:00:00    13:10:00
c       6       12:15:00    
a       4       12:30:00    14:05:00