假设表的内容看起来如下:
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
。
我们应该再有两个表 - 与可比的顺序上相对应checkout
和checkin
- 以及它们发生的顺序,从而使我们开始和结束时间为设备的每个单独的会话。
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)
给人的输出:这两个相应的表格现在可以简单地在rank
和eno
(设备号),我们可以计算的sessions
计数以及SUM
了每个checkout
和checkin
之间的时间差来加入为:
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。
我可以假设签出和签入将总是图案? – McNets
是的 - 结账将始终在入住日期之前,没有重叠 – andrewb
是否有可能在23:55:00'检出设备,并在第二天,在02:00点退房'?会议将归因于哪一天? –