1. 程式人生 > 其它 >9-固定時間段內的工作時間求和

9-固定時間段內的工作時間求和

技術標籤:# SQL例項sql

類似於使用打卡時間求一段時間內的工作時間之和,給出的表資料大致是這樣的。
在這裡插入圖片描述
ID:車間ID
gid:裝置id
ACTIVITY:型別 ,有兩種:in 開啟, out 關閉
時間:啟動或者關閉的時間點

現在的要求是輸入一個開始時間 和一個結束時間 求每臺裝置(同一車間的同一裝置)的在此範圍內的工作時間。
異常資料處理:
1.重複資料需要去重
2.同一臺裝置連續的in 需要取最後一個 
3.連續的out需要取第一個
4.如果一個時間段的開始時間小於輸入的開始時間,則按照輸入開始時間計算
5.如果一個時間段的結束時間大於輸入的結束時間,則按照輸入結束時間計算
上面的表輸入

在這裡插入圖片描述
最終得到的結果是
在這裡插入圖片描述
資料在下方:

CREATE TABLE "SYSTEM"."AAREPORT" (  "ID" VARCHAR2(255 BYTE) ,  
"ACTIVITY" VARCHAR2(255 BYTE) ,  "TXNTIMESTAMP" DATE , 
 "GID" VARCHAR2(255 BYTE) )TABLESPACE "SYSTEM"LOGGINGNOCOMPRESSPCTFREE 10INITRANS 1STORAGE 
 (
INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)PARALLEL 1NOCACHEDISABLE ROW MOVEMENT; -- ------------------------------ Records of AAREPORT-- ---------------------------- INSERT INTO "SYSTEM"."AAREPORT" VALUES (
'1', 'in', TO_DATE('2020-07-15 08:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 'a'); INSERT INTO "SYSTEM"."AAREPORT" VALUES ('1', 'out', TO_DATE('2020-07-16 03:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 'a'); INSERT INTO "SYSTEM"."AAREPORT" VALUES ('2', 'in', TO_DATE('2020-07-15 08:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 'b'); INSERT INTO "SYSTEM"."AAREPORT" VALUES ('3', 'in', TO_DATE('2020-07-15 10:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 'a'); INSERT INTO "SYSTEM"."AAREPORT" VALUES ('3', 'out', TO_DATE('2020-07-16 02:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 'a'); INSERT INTO "SYSTEM"."AAREPORT" VALUES ('3', 'in', TO_DATE('2020-07-16 10:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 'a'); INSERT INTO "SYSTEM"."AAREPORT" VALUES ('4', 'in', TO_DATE('2020-07-16 01:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 'a'); INSERT INTO "SYSTEM"."AAREPORT" VALUES ('4', 'out', TO_DATE('2020-07-16 02:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 'a'); INSERT INTO "SYSTEM"."AAREPORT" VALUES ('4', 'in', TO_DATE('2020-07-16 09:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 'a'); INSERT INTO "SYSTEM"."AAREPORT" VALUES ('4', 'out', TO_DATE('2020-07-17 21:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 'a'); INSERT INTO "SYSTEM"."AAREPORT" VALUES ('1', 'in', TO_DATE('2020-07-15 07:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 'b'); INSERT INTO "SYSTEM"."AAREPORT" VALUES ('1', 'out', TO_DATE('2020-07-16 04:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 'b'); INSERT INTO "SYSTEM"."AAREPORT" VALUES ('3', 'in', TO_DATE('2020-07-18 12:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 'b'); INSERT INTO "SYSTEM"."AAREPORT" VALUES ('3', 'in', TO_DATE('2020-07-17 08:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 'b'); INSERT INTO "SYSTEM"."AAREPORT" VALUES ('3', 'out', TO_DATE('2020-07-17 18:00:00', 'SYYYY-MM-DD HH24:MI:SS'), 'b');

答案:

with t_x as  ---使用者引數輸入
(select &輸入開始時間 as start_time ,&輸入結束時間 as end_time from dual)
,
t10 as     ---用於對重複資料去重和對最後無out資料的容錯
(select distinct id,gid,activity,txntimestamp
from system.aareport  union all
select distinct id,gid,'out' as  activity,date'4712-12-31' as txntimestamp
from system.aareport
)
,t2 as   --- 對資料進行編號
(
select  id,gid,activity,txntimestamp,
row_number()over(partition by id,gid order by txntimestamp) as flag
from t10
)
-----將開始時間和結束時間寫在同一行中,並對實際時間和傳入時間進行對比選取
-----最後計算總時間的和
select t3.id,t3.gid,min(greatest(t3.txntimestamp,t5.start_time)) as start_time ,
max(least(t4.txntimestamp,t5.end_time)) as end_time ,
sum(least(t4.txntimestamp,t5.end_time)-
greatest(t3.txntimestamp,t5.start_time))*24 as sum_time
from t2 t3 , t2 t4,t_x t5
where t3.id=t4.id and t3.gid =t4.gid and
t3.flag=t4.flag-1  and t3.txntimestamp <=t5.end_time
and t4.txntimestamp >=t5.start_time
and t3.activity ='in'
and t4.activity ='out'
group by t3.id  ,t3.gid