MYSQL - 使用下一个日期更新临时表

时间:2017-02-03 16:02:13

标签: mysql

我有一个包含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之后获取下一个检查日期”。

1 个答案:

答案 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编写类似的查询。

然后我们将有两个表 - 在可比顺序中具有相应的checkoutcheckin - 以及它们发生的顺序,从而为设备的每个单独会话提供开始和结束时间。这两个相应的表现在可以简单地通过rankeno(设备编号)连接,我们可以计算sessions的计数以及SUM之间的时差每个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)

将输出作为:

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

Demo link