2013-10-22 122 views
1

想象一下帶鎖門的房間。門附近有讀卡器。要打開門,您需要將您的卡放入讀卡器。Oracle如何選擇時間間隔

我有2代表與我的Oracle數據庫事件 - 項(門從打開的房間外) 退出(門被從房間內打開)

我要的是選擇presense間隔像 員工1在某天從10:00到11:00以及從12:00到18:00在房間裏。

但也有3個問題

  1. 有時用戶打開門,但不離開房間。
  2. 有時一個用戶打開門,另一個用戶和他一起出門,而 門一次打開。
  3. 數據的大小(以每桌約100K)

和問題:

  1. 什麼是選擇presense間隔
  2. 最好的辦法是有什麼辦法可以創建快速刷新物化視圖解決這個?

下面是示例

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個退出使用秒,請先忽略

+2

什麼是你想要實現的業務規則測試一樣嗎?如果用戶打開門但未退出,您如何確定他們何時實際退出?如果用戶關注某人,你如何確定?如果您發現用戶在時間B輸入了時間A並再次輸入,那麼您如何確定第一個時間間隔何時結束(假設用戶已與其他人退出)?如果您看到用戶在A處輸入,在B處退出並在C處退出,您是否認爲他們僅存在於A和B之間?你怎麼知道他們是不是不開門就是開門? –

+0

檢查我提供的樣品。它是相當具有描述性的。總之如果先有2個連續使用,則忽略第二個。如果連續有2個退出使用秒,請先忽略 –

+1

爲什麼日期和時間未存儲在同一字段中? – user2275460

回答

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

u能在http://sqlfiddle.com/#!4/72ac2/9

+0

它是如何工作的 - 你能解釋一下嗎? –

+0

這一個是真棒.... –

+0

快樂它爲你工作!它首先將所有事件時間從條目映射到退出時的所有更大的偶數時間。然後對於每個輸入時間,它需要最近的退出時間。然後再次爲每個退出時間花費最近的入場時間 – user2342436

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; 
+0

固定括號後,employee_id employeeid它仍然不起作用SQL錯誤:ORA-25154:USING子句的列部分不能有限定符 –