我個人并不推薦在實際開發中使用存盤程序,充滿了各種的不方便,之所以寫這東西,全在于學習,如果有高手看到我的內容有問題,可以隨時指出或向我開炮,
需求:
在生產中常常出現計算兩個時間差的業務,比如總宕機時間、總開通會員時間等等,,,但是這些時間往往不是連貫的,斷斷續續,甚至可能會出現重疊的情況,無法直接求出時間差,
例如:


開車:
一開始,我想的是用單條SQL實作,例如:↓
SELECT TIMESTAMPDIFF(MINUTE, '2021-08-19 14:30:00', '2021-08-19 15:00:00') FROM DUAL;
我發現,資料庫資料千千萬,不可能這樣,也不可能用UNION這種東西去拼接,資料很多,就一定會有回圈,所以,在不使用Java語言的情況下,我選擇嘗試用存盤程序來解決以下這個問題,
思路:
首先,一次進入回圈的資料不會進行計算,防止后邊的資料和它有重疊,
從第二條資料開始,就要判斷開始時間是否和上一個資料重疊,如果重疊,則校驗結束時間是否也重疊,如果重疊我就啥也不干,不重疊,則把這個值賦給上一次的資料的結束時間,
如果開始時間不再范圍內,那么需要判斷開始時間是在上一次時間的之前還是之后
如果這個范圍之前,把這個值賦給上一次的資料的開始時間,
在這個范圍之后,計算并賦值
最后一次回圈也要計算并賦值
實作:
首先創建表,模擬資料
CREATE TABLE test01 (
id int(32) unsigned NOT NULL AUTO_INCREMENT,
start_time datetime NOT NULL,
end_time datetime NOT NULL,
PRIMARY KEY (`id`)
)
INSERT INTO test01(id, start_time, end_time) VALUES (1, '2021-08-18 16:27:51', '2021-08-18 17:27:59');
INSERT INTO test01(id, start_time, end_time) VALUES (2, '2021-08-18 17:20:26', '2021-08-18 20:10:37');
INSERT INTO test01(id, start_time, end_time) VALUES (3, '2021-08-18 22:05:57', '2021-08-18 23:55:20');

創建存盤程序:
CREATE PROCEDURE sumTime()
BEGIN
-- 定義變數
-- 是否首次
DECLARE is_old int(1) DEFAULT 0;
-- 上一次資料
DECLARE old_start_time datetime;
DECLARE old_end_time datetime;
-- 本次資料
DECLARE start_time datetime;
DECLARE end_time datetime;
-- 回傳結果
DECLARE num int(32) DEFAULT 0;
-- 回圈結束開關
DECLARE done int DEFAULT 0;
-- 創建游標(查詢資料庫資料)
DECLARE list CURSOR FOR SELECT a.start_time, a.end_time FROM test01 a;
-- 定義最后一次回圈時設定 回圈結束開關 為 1
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
-- 開啟游標
OPEN list;
-- 開啟回圈
posLoop:LOOP
-- 取值 將當前回圈的值取出 賦值給當前資料變數
FETCH list INTO start_time,end_time;
-- 判斷是否首次
if (is_old = 0) THEN
SET is_old = 1;
SET old_start_time = start_time;
SET old_end_time = end_time;
-- 否則
ELSE
-- 校驗是否在區間內
if (start_time >= old_start_time AND start_time <= old_end_time) THEN
-- 校驗結束時間是否不在在區間內
if (end_time < old_start_time OR end_time > old_end_time) THEN
SET old_end_time = end_time;
END IF;
-- 否則
ELSE
if (start_time < old_start_time ) THEN
SET old_start_time = start_time;
ELSE
SET num = num + TIMESTAMPDIFF(MINUTE, old_start_time, old_end_time);
SET old_start_time = start_time;
SET old_end_time = end_time;
END IF;
END IF;
END IF;
-- 校驗是否最后一次回圈
IF done=1 THEN
SET num = num + TIMESTAMPDIFF(MINUTE, old_start_time, old_end_time);
LEAVE posLoop;
END IF;
-- 結束回圈
END LOOP posLoop;
-- 關閉游標
CLOSE list;
SELECT num;
END;
-- 呼叫存盤程序
call sumTime();

-- 洗掉存盤程序
drop procedure if exists sumTime;
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/295392.html
標籤:java
下一篇:Java垃圾回識訓制(GC)
