我有一个包含EquipmentNo(VARCHAR),ActionType(VARCHAR)和ActionDate(DateTime)列的表
当用户检出某些设备时,会添加一行,如下所示:
EquipmentNo: 123
ActionType: 'checkout'
ActionDate: '2017-02-03 09:05:27'
当他们检查那台设备时:
EquipmentNo: 123
ActionType: 'checkin'
ActionDate: '2017-02-03 10:32:46'
每天可以多次检查/检查一件设备,所以我们说装备号123在同一天晚些时候再检查/检查。
EquipmentNo: 123
ActionType: 'checkout'
ActionDate: '2017-02-03 11:15:27'
EquipmentNo: 123
ActionType: 'checkout'
ActionDate: '2017-02-03 11:30:55'
我需要编写一个查询来计算所有会话的持续时间(结帐和相应的检查时间之间的差异)。查询还需要总结设备所拥有的会话数,在我们的例子中,它有2个会话,持续时间为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 :(得分: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
然后也可以为checkin
编写类似的查询。
然后我们将有两个表 - 在可比顺序中具有相应的checkout
和checkin
- 以及它们发生的顺序,从而为设备的每个单独会话提供开始和结束时间。这两个相应的表现在可以简单地通过rank
和eno
(设备编号)连接,我们可以计算sessions
的计数以及SUM
之间的时差每个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)
将输出作为:
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
中。