2017-02-03 67 views
1

我有EquipmentNo(VARCHAR),操作类型(VARCHAR)和ActionDate(DATETIME)列的表更新临时表MYSQL - 与下一个日期

当用户签了一些设备的行会像下面这样说:

EquipmentNo: 123 
ActionType: 'checkout' 
ActionDate: '2017-02-03 09:05:27' 

当他们检查设备回:

EquipmentNo: 123 
ActionType: 'checkin' 
ActionDate: '2017-02-03 10:32:46' 

设备的单件可以签出/每天多次检查,因此,可以说EquipmentNo 123有另一次结账/同一天晚些时候入住。

EquipmentNo: 123 
ActionType: 'checkout' 
ActionDate: '2017-02-03 11:15:27' 

EquipmentNo: 123 
ActionType: 'checkout' 
ActionDate: '2017-02-03 11:30:55' 

我需要编写一个查询计算所有会话的持续时间(结账和相应的检查时间之间的差异)。该查询还需要总结该设备有多少会话,在我们的例子中,它有两个会话,持续时间为102分钟。

这里是我迄今为止

CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 AS (
SELECT EquipmentNo, MIN(ActionDate) AS CheckOutDate, 
NULL AS CheckInDate, COUNT(*) AS Sessions 
FROM EquipmentSessions WHERE ActionType = 'checkout' GROUP BY EquipmentNo, ActionDate); 

这将产生类似

123 | 2017-02-03 09:05:27 | NULL | 1 
123 | 2017-02-03 11:15:27 } NULL | 1 

我似乎什么不能做的就是锻炼如何构建使用此表作为源我的更新语句并基本上说“每个EquipmentNo的sourceTable.CheckOutDate后获得下一次检查日期”。

+0

我可以假设签出和签入将总是图案? – McNets

+0

是的 - 结账将始终在入住日期之前,没有重叠 – andrewb

+0

是否有可能在23:55:00'检出设备,并在第二天,在02:00点退房'?会议将归因于哪一天? –

回答

1

假设表的内容看起来如下:

CREATE TABLE eqp (eno int, action_type varchar(20), action_date timestamp); 

INSERT INTO eqp VALUES(124, 'checkout', '2017-02-03 09:00:00'); 
INSERT INTO eqp VALUES(123, 'checkout', '2017-02-03 09:05:27'); 
INSERT INTO eqp VALUES(124, 'checkin', '2017-02-03 10:00:00'); 
INSERT INTO eqp VALUES(123, 'checkin', '2017-02-03 10:32:46'); 
INSERT INTO eqp VALUES(123, 'checkout', '2017-02-03 11:15:27'); 
INSERT INTO eqp VALUES(123, 'checkin', '2017-02-03 11:30:55'); 

INSERT INTO eqp VALUES(123, 'checkout', '2017-02-04 09:00:00'); 
INSERT INTO eqp VALUES(123, 'checkin', '2017-02-04 10:00:00'); 
INSERT INTO eqp VALUES(123, 'checkout', '2017-02-04 15:00:00'); 
INSERT INTO eqp VALUES(123, 'checkin', '2017-02-04 17:00:00'); 
INSERT INTO eqp VALUES(123, 'checkout', '2017-02-04 18:30:00'); 
INSERT INTO eqp VALUES(123, 'checkin', '2017-02-04 19:00:00'); 


因此,假设如下:

  • checkout总是先checkin为设备
  • 所采取的行动将是在同一天内完成,并且
  • (暗示假设)已签出将有创纪录的检查表中(执行此期望的操作之前,每个设备)

我们可以编写一个查询来获取所有checkout事件首先排序由设备,然后通过时间在以使他们发生,并分配一个rank到每一条记录牵强:

SELECT @checkoutrank := @checkoutrank + 1 AS rank, eno, action_type, action_date 
    FROM eqp, (SELECT @checkoutrank := 0) r 
WHERE action_type='checkout' 
ORDER BY eno ASC, action_date ASC 

这给:

rank | eno  | action_type | action_date 
---------------------------------------------------------- 
1  | 123  | checkout  | 2017-02-03 09:05:27 
2  | 123  | checkout  | 2017-02-03 11:15:27 
3  | 123  | checkout  | 2017-02-04 09:00:00 
4  | 123  | checkout  | 2017-02-04 15:00:00 
5  | 123  | checkout  | 2017-02-04 18:30:00 
6  | 124  | checkout  | 2017-02-03 09:00:00 

类似的查询可以TH也写为checkin

我们应该再有两个表 - 与可比的顺序上相对应checkoutcheckin - 以及它们发生的顺序,从而使我们开始和结束时间为设备的每个单独的会话。

SELECT checkin.eno, DATE(checkin.action_date) AS session_date, 
    COUNT(*) AS sessions, 
    SUM(TIMESTAMPDIFF(SECOND, checkout.action_date, checkin.action_date)) 
      AS sesssion_duration 
FROM 
    (
     SELECT @checkoutrank := @checkoutrank + 1 AS rank, eno, action_type, action_date 
      FROM eqp, (SELECT @checkoutrank := 0) r 
     WHERE action_type='checkout' 
     ORDER BY eno ASC, action_date ASC 
    ) checkout 

INNER JOIN 
    (
     SELECT @checkinrank := @checkinrank + 1 AS rank, eno, action_type, action_date 
      FROM eqp, (SELECT @checkinrank := 0) r 
     WHERE action_type='checkin' 
     ORDER BY eno ASC, action_date ASC 
    ) checkin 

    ON checkout.rank = checkin.rank 
    AND checkout.eno = checkin.eno 

GROUP BY checkin.eno, DATE(checkin.action_date) 

给人的输出:这两个相应的表格现在可以简单地在rankeno(设备号),我们可以计算的sessions计数以及SUM了每个checkoutcheckin之间的时间差来加入为:

eno  | session_date | sessions | session_duration 
-------------------------------------------------------------- 
123  | 2017-02-03 |  2  | 6167 
123  | 2017-02-04 |  3  | 12600 
124  | 2017-02-03 |  1  | 3600 

上述session_duration计算在SECOND S表示简单起见以及精度。

Demo link

+0

完美!正是我需要的 – andrewb

+1

感谢您的确认,@andrewb!你认为更新问题的标题以表明它与连续事件/时间戳/行有关吗?干杯! –