2017-02-03 64 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!你認爲更新問題的標題以表明它與連續事件/時間戳/行有關嗎?乾杯! –