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

Mysql 将具有时间戳的几行合并为具有开始和结束时间戳的一行,mysql,sql,Mysql,Sql,我正在尝试从库存系统后端提取一些SQL报告 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

我正在尝试从库存系统后端提取一些SQL报告

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   
我试图报告的表有一个“action”列(用于跟踪签入或签出)和一个“timestamp”列

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   
我正试图为每个具有开始时间和结束时间的用户/资产组合将它们重新格式化为行

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   
样本数据:

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   
当前:

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   
渴望的

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   
**不需要,只是为了表的正确性

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   
每个用户-资产对都可以重复,并且需要显示为两行,这一事实使问题变得更加复杂

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   

想法?

MySql 8.0使用
row\u number()
窗口函数来匹配out/in

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   
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 

MySql 8.0使用
row\u number()
窗口函数来匹配out/in

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   
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 

这里有一个MySql 8的查询,它使用一个MIN OVER来计算输入时间

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   
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;
dbfiddle测试

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   
结果:

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   
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

下面是一个针对MySql 8的查询,它使用一个MIN OVER来计算in_时间

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   
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;
dbfiddle测试

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   
结果:

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   
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

当一个用户-资产对重复出现时,会有多少out-in事件被配对?啊,忘了DBMS。谢谢@a_horse___,没有_name@Serg修改示例以显示b-4的结果。当用户资产对重复时,out-in事件将如何配对?啊,忘了DBMS。谢谢@a_horse___,没有_name@Serg修改示例以显示b-4的结果。您的两个查询(您和@serg)都为我提供了答案,谢谢。现在查找所有高级SQL,这样我就可以解包这个查询了,lol。您的两个查询(您和@serg)都为我解答了,谢谢。现在查找所有高级SQL,这样我就可以解包这个查询了,哈哈。你的两个查询(你和@lukstorms)都为我解答了,谢谢。现在查找所有高级SQL,这样我就可以解包这个查询了,哈哈。你的两个查询(你和@lukstorms)都为我解答了,谢谢。现在要查找所有高级SQL,以便解压此查询,lol。