我希望编写一个查询,为具有多个访问点(TOTAL_HOURS_WORKED
)和多个条目(DEVICE_ID
或{{}的考勤管理系统中的每位员工生成ROW_ID
1}})。
到目前为止,我认为最好的方法是获得第一个' CLOCK_IN'时间并从最后一个&CLACK_OUT'中减去它。时间;然后从中减去任何后续clockin或out的总和。以下是我迄今为止获得的数据和数据:
如上所示,有许多条目,甚至一些错误或双重条目。我希望输出反映出像这样的东西
ENTRY_ID
这是我迄今为止编写的代码,它生成了上述表格:
PIN 326
TOTAL HOURS: 06:15:49 (hh:mm:ss)
答案 0 :(得分:0)
我把它弄清楚但是现在停在一些PL SQL LOOPS上。将张贴到另一个线上。
-- ALL ENTRIES INTO TEMP_TABLE
INSERT INTO ACC_FINAL_TIMES (ROW_NUM, ENTRY_ID, ENTRY_DATE, ENTRY_TIME, TIME, PIN, DEVICE_ID, STATE, EVENT_POINT_NAME, DUPLICATE)
WITH BDEV_RPT2 AS
-- LAST OUT ENTRY
(
SELECT *
FROM (SELECT ROW_NUMBER()OVER(ORDER BY TIME DESC) ROW_NUM, a.* FROM acc_time_logs a WHERE PIN='944' AND ENTRY_DATE='20160117' AND STATE IN ('1','2') AND DEVICE_ID IN ('18','10','6','9') ORDER BY TIME DESC)
WHERE ROW_NUM IN ('1','2') AND DEVICE_ID='18' OR (ROW_NUM='1' AND DEVICE_ID IN ('10','6','9') AND NOT EXISTS(SELECT NULL FROM (SELECT ROW_NUMBER()OVER(ORDER BY TIME DESC) ROW_NUM, a.* FROM acc_time_logs a WHERE PIN='944' AND ENTRY_DATE='20160117' AND STATE IN ('1','2') AND DEVICE_ID IN ('18','10','6','9') ORDER BY TIME DESC) WHERE ROW_NUM IN ('1','2') AND DEVICE_ID='18'))
)
,BDEV_RPT3 AS
-- FIRST IN ENTRY
(
SELECT *
FROM (SELECT ROW_NUMBER()OVER(ORDER BY TIME ASC) ROW_NUM, a.* FROM acc_time_logs a WHERE PIN='944' AND ENTRY_DATE='20160117' AND STATE IN ('0','2') AND DEVICE_ID IN ('21','10','6','9') ORDER BY TIME ASC)
WHERE ROW_NUM IN ('1','2') AND DEVICE_ID='21' OR (ROW_NUM='1' AND DEVICE_ID IN ('10','6','9') AND NOT EXISTS(SELECT NULL FROM (SELECT ROW_NUMBER()OVER(ORDER BY TIME ASC) ROW_NUM, a.* FROM acc_time_logs a WHERE PIN='944' AND ENTRY_DATE='20160117' AND STATE IN ('0','2') AND DEVICE_ID IN ('21','10','6','9') ORDER BY TIME ASC) WHERE ROW_NUM IN ('1','2') AND DEVICE_ID='21'))
)
,ENTRY_DUP1 AS
-- REMOVE DUPLICATE ROWS OUT
(
SELECT ROW_NUMBER()OVER(ORDER BY TIME DESC) ROW_NUM, ENTRY_ID, ENTRY_DATE, ENTRY_TIME, TIME, PIN, DEVICE_ID, STATE, EVENT_POINT_NAME FROM acc_time_logs WHERE PIN='944' AND ENTRY_DATE='20160117' AND STATE
IN ('1','2') AND DEVICE_ID IN ('18','10','6','9') AND ENTRY_ID NOT IN (SELECT ENTRY_ID FROM BDEV_RPT2)
)
,ENTRY_INT1 AS
-- REMOVE DUPLICATE ROWS OUT
(
SELECT a.ROW_NUM, a.ENTRY_ID, a.ENTRY_DATE, a.ENTRY_TIME, a.TIME, a.PIN, a.DEVICE_ID, a.STATE, a.EVENT_POINT_NAME FROM ENTRY_DUP1 a INNER JOIN ENTRY_DUP1 b ON a.ROW_NUM = b.ROW_NUM + 1 WHERE DATEDIFF(a.TIME, b.TIME) < 60 AND a.ROW_NUM <> 1
)
,ENTRY_DUP2 AS
-- REMOVE DUPLICATE ROWS IN
(
SELECT ROW_NUMBER()OVER(ORDER BY TIME DESC) ROW_NUM, ENTRY_ID, ENTRY_DATE, ENTRY_TIME, TIME, PIN, DEVICE_ID, STATE, EVENT_POINT_NAME FROM acc_time_logs WHERE PIN='944' AND ENTRY_DATE='20160117' AND STATE IN ('0','2') AND DEVICE_ID IN ('21','10','6','9') AND ENTRY_ID NOT IN (SELECT ENTRY_ID FROM BDEV_RPT3)
)
,ENTRY_INT2 AS
-- REMOVE DUPLICATE ROWS IN
(
SELECT a.ROW_NUM, a.ENTRY_ID, a.ENTRY_DATE, a.ENTRY_TIME, a.TIME, a.PIN, a.DEVICE_ID, a.STATE, a.EVENT_POINT_NAME FROM ENTRY_DUP2 a INNER JOIN ENTRY_DUP2 b ON a.ROW_NUM = b.ROW_NUM + 1 WHERE DATEDIFF(a.TIME, b.TIME) < 60 AND a.ROW_NUM <> 1
)
SELECT ROW_NUMBER()OVER(ORDER BY TIME ASC) ROW_NUM, ENTRY_ID, ENTRY_DATE, ENTRY_TIME, TIME, PIN, DEVICE_ID, STATE, EVENT_POINT_NAME, NULL FROM
(
SELECT ENTRY_ID, ENTRY_DATE, ENTRY_TIME, TIME, PIN, DEVICE_ID, STATE, EVENT_POINT_NAME FROM ENTRY_DUP2 c WHERE NOT EXISTS(SELECT * FROM ENTRY_INT2 d WHERE c.ROW_NUM = d.ROW_NUM)
UNION ALL
SELECT ENTRY_ID, ENTRY_DATE, ENTRY_TIME, TIME, PIN, DEVICE_ID, STATE, EVENT_POINT_NAME FROM ENTRY_DUP1 c WHERE NOT EXISTS(SELECT * FROM ENTRY_INT1 d WHERE c.ROW_NUM = d.ROW_NUM)) a ORDER BY TIME ASC
=====================================================================================================================================================================
=====================================================================================================================================================================
=====================================================================================================================================================================
=====================================================================================================================================================================
=====================================================================================================================================================================
=====================================================================================================================================================================
=====================================================================================================================================================================
=====================================================================================================================================================================
-- CHECK FIRST ROW OUT ENTRY
DELETE FROM ACC_FINAL_TIMES WHERE ROW_NUM=1 AND STATE=0
-- UPDATE MAIN DOOR ENTRIES
UPDATE acc_final_times a
SET STATE =
CASE
WHEN EVENT_POINT_NAME = 'Main Check-In-1'
THEN 0
ELSE 1
END
WHERE STATE='2'
--MARK IRREGULAR ENTRY'S AS DUPLICATE
exec IRR_AS_DUP
CREATE PROCEDURE IRR_AS_DUP IS
CURSOR ftime_logs IS
SELECT * FROM ACC_FINAL_TIMES WHERE DUPLICATE IS NULL;
BEGIN
FOR x IN ftime_logs LOOP
UPDATE ACC_FINAL_TIMES a
SET DUPLICATE =
CASE
WHEN a.STATE=x.STATE
THEN 1
ELSE 0
END
WHERE a.ROW_NUM=x.ROW_NUM+1;
END LOOP;
END IRR_AS_DUP;
/
-- REMOVE DUPLICATE OR IRREGULAR ENTRIES
DELETE ACC_FINAL_TIMES WHERE DUPLICATE = 1
-- RENUMBER ROWS
UPDATE ACC_FINAL_TIMES SET ROW_NUM=ROWNUM
-- HOUR MISSED FROM WORK
SELECT
a.ENTRY_ID,
a.ENTRY_DATE,
a.PIN,
a.ENTRY_TIME AS OUT_ENTRY,
b.ENTRY_TIME AS IN_ENTRY,
DATEDIFF(a.TIME,b.TIME) BREAK_TIMES
FROM ACC_FINAL_TIMES a
INNER JOIN ACC_FINAL_TIMES b
ON a.ROW_NUM = b.ROW_NUM-1 AND a.STATE='1' AND b.STATE='0'
-- IRREGULAR ENTRIES REPORT
SELECT a.* FROM acc_final_times a
LEFT JOIN (
SELECT
b.ROW_NUM AS ROW_A,
c.ROW_NUM AS ROW_B
FROM acc_final_times b
INNER JOIN acc_final_times c
ON b.ROW_NUM=c.ROW_NUM-1 AND b.STATE='1' AND c.STATE='0'
) d
ON a.ROW_NUM IN (d.ROW_A, d.ROW_B)
WHERE d.ROW_A IS NULL
-- TOTAL HOURS WORKED
,TIME_DIFF AS
(
SELECT
a.ENTRY_ID,
a.ENTRY_DATE,
a.PIN,
a.ENTRY_TIME OUT_ENTRY,
b.ENTRY_TIME IN_ENTRY,
DATEDIFF(a.TIME,b.TIME) BREAK_TIMES
FROM acc_final_times a
INNER JOIN acc_final_times b
ON a.ROW_NUM = b.ROW_NUM-1 AND a.STATE='1' AND b.STATE='0'
)
SELECT TO_CHAR(TRUNC(SYSDATE) + NUMTODSINTERVAL (TOTAL_SECS, 'second'),'hh:mi:ss') TOTAL_HOURS FROM (SELECT DATEDIFF((SELECT TIME FROM BDEV_RPT3),(SELECT TIME FROM BDEV_RPT2))-(SELECT SUM(BREAK_TIMES) FROM TIME_DIFF) TOTAL_SECS FROM DUAL)