想象一下带锁门的房间。门附近有读卡器。要打开门,您需要将卡放入读卡器。
我的Oracle数据库中有两个包含事件的表 - 参赛作品(门从房间外面打开) 出口(门从房间内打开)
我想要的只是选择presense的间隔 员工1在某一天从10:00到11:00以及从12:00到18:00在房间里。
但是有3个问题
问题:
这是样本
drop table entries;
drop table exits;
CREATE TABLE ENTRIES
(
"EVENTDATE" DATE NOT NULL,
"EVENTTIME" DATE NOT NULL,
"EMPLOYEEID" NUMBER NOT NULL
);
CREATE TABLE EXITS
(
"EVENTDATE" DATE NOT NULL,
"EVENTTIME" DATE NOT NULL,
"EMPLOYEEID" NUMBER NOT NULL
);
delete from ENTRIES;
delete from exits;
Insert into ENTRIES (EMPLOYEEID,EVENTDATE,EVENTTIME) values (8,to_date('01-AUG-13 00:00:00','DD-MON-RR HH24:MI:SS'),to_date('01-JAN-00 08:44:00','DD-MON-RR HH24:MI:SS'));
Insert into ENTRIES (EMPLOYEEID,EVENTDATE,EVENTTIME) values (8,to_date('01-AUG-13 00:00:00','DD-MON-RR HH24:MI:SS'),to_date('01-JAN-00 12:18:00','DD-MON-RR HH24:MI:SS'));
Insert into ENTRIES (EMPLOYEEID,EVENTDATE,EVENTTIME) values (8,to_date('01-AUG-13 00:00:00','DD-MON-RR HH24:MI:SS'),to_date('01-JAN-00 12:19:00','DD-MON-RR HH24:MI:SS'));
Insert into ENTRIES (EMPLOYEEID,EVENTDATE,EVENTTIME) values (8,to_date('01-AUG-13 00:00:00','DD-MON-RR HH24:MI:SS'),to_date('01-JAN-00 12:22:00','DD-MON-RR HH24:MI:SS'));
Insert into ENTRIES (EMPLOYEEID,EVENTDATE,EVENTTIME) values (8,to_date('01-AUG-13 00:00:00','DD-MON-RR HH24:MI:SS'),to_date('01-JAN-00 12:37:00','DD-MON-RR HH24:MI:SS'));
Insert into ENTRIES (EMPLOYEEID,EVENTDATE,EVENTTIME) values (8,to_date('01-AUG-13 00:00:00','DD-MON-RR HH24:MI:SS'),to_date('01-JAN-00 12:38:00','DD-MON-RR HH24:MI:SS'));
Insert into ENTRIES (EMPLOYEEID,EVENTDATE,EVENTTIME) values (8,to_date('01-AUG-13 00:00:00','DD-MON-RR HH24:MI:SS'),to_date('01-JAN-00 12:39:00','DD-MON-RR HH24:MI:SS'));
Insert into ENTRIES (EMPLOYEEID,EVENTDATE,EVENTTIME) values (8,to_date('01-AUG-13 00:00:00','DD-MON-RR HH24:MI:SS'),to_date('01-JAN-00 12:40:00','DD-MON-RR HH24:MI:SS'));
Insert into ENTRIES (EMPLOYEEID,EVENTDATE,EVENTTIME) values (8,to_date('01-AUG-13 00:00:00','DD-MON-RR HH24:MI:SS'),to_date('01-JAN-00 13:22:00','DD-MON-RR HH24:MI:SS'));
Insert into EXITS (EMPLOYEEID,EVENTDATE,EVENTTIME) values (8,to_date('01-AUG-13 00:00:00','DD-MON-RR HH24:MI:SS'),to_date('01-JAN-00 12:40:00','DD-MON-RR HH24:MI:SS'));
Insert into EXITS (EMPLOYEEID,EVENTDATE,EVENTTIME) values (8,to_date('01-AUG-13 00:00:00','DD-MON-RR HH24:MI:SS'),to_date('01-JAN-00 12:36:00','DD-MON-RR HH24:MI:SS'));
Insert into EXITS (EMPLOYEEID,EVENTDATE,EVENTTIME) values (8,to_date('01-AUG-13 00:00:00','DD-MON-RR HH24:MI:SS'),to_date('01-JAN-00 11:55:00','DD-MON-RR HH24:MI:SS'));
Insert into EXITS (EMPLOYEEID,EVENTDATE,EVENTTIME) values (8,to_date('01-AUG-13 00:00:00','DD-MON-RR HH24:MI:SS'),to_date('01-JAN-00 18:02:00','DD-MON-RR HH24:MI:SS'));
所需的结果如下:
"EMPLOYEID" "EVENTDATE" "ENTERTIME" "LEAVETIME"
8 01-AUG-13 00:00:00 01-JAN-00 08:44:00 01-JAN-00 11:55:00
8 01-AUG-13 00:00:00 01-JAN-00 12:18:00 01-JAN-00 12:36:00
8 01-AUG-13 00:00:00 01-JAN-00 12:37:00 01-JAN-00 12:40:00
8 01-AUG-13 00:00:00 01-JAN-00 13:22:00 01-JAN-00 18:02:00
更新
如果有2个连续使用,请先忽略秒。 如果连续有2个出口使用秒,则忽略第一个
答案 0 :(得分:2)
请找到以下测试的查询: -
SELECT employeeid,eventdate,entry_time,exit_time
FROM
(SELECT employeeid,eventdate,entry_time,exit_time,
rank() over (partition BY employeeid,eventdate,exit_time ORDER BY entry_time ASC) et
FROM
(SELECT t.employeeid,t.eventdate,t.eventtime entry_time,
o.eventtime exit_time,
rank() over (partition BY t.employeeid,t.eventdate,t.eventtime ORDER BY o.eventtime ASC) mt
FROM entries t,exits o
WHERE t.employeeid = o.employeeid AND t.eventdate=o.eventdate
AND t.eventtime < o.eventtime) WHERE mt =1)WHERE et=1
答案 1 :(得分:0)
我没有测试看看是否有效,我忽略了事件时间,但尝试以下方法。 基本上,我们想要找到真正的输入和真实退出(真正的输入:输入/退出,之间没有输入,真正的退出:退出/输入,之间没有退出)。我们加入两个(加入真正的退出两次)并显示进入/退出退出后的输入/退出,输入退出之间没有其他退出。
select
a.employee_id
, true_enterdate
, true_exitdate
from (
select
ent1.eventdate true_enterdate -- enter/exit with no enter between
, employee_id
from
entries ent1
join exits ex1 using (employee_id)
left outer join entries ent2 using (employee_id)
where 1=1
and ent1.eventdate < ex1.eventdate
and ent2.eventdate > ent1.eventdate
and ent2.eventdate < ex1.eventdate
and ent2.employee_id is null
) a join (
select
ent1.eventdate true_exitdate -- exit/enter with no exit between
, employee_id
from
entries ent1
join exits ex1 using (employee_id)
left outer join exits ex2 using (employee_id)
where 1=1
and ent1.eventdate < ex1.eventdate
and ex2.eventdate > ent1.eventdate
and ex2.eventdate < ex1.eventdate
and ex2.employee_id is null
) b using (employee_id)
left outer join (
select
ent1.eventdate true_exitdate2 -- exit/enter with no exit between
, employee_id
from
entries ent1
join exits ex1 using (employee_id)
left outer join exits ex2 using (employee_id)
where 1=1
and ent1.eventdate < ex1.eventdate
and ex2.eventdate > ent1.eventdate
and ex2.eventdate < ex1.eventdate
and ex2.employee_id is null
) c using (employee_id)(
where 1=1
and true_enterdate < true_exitdate
and true_exitdate2 > true_enterdate
and true_exitdate2 < true_exitdate
and c.employee_id is null;