DATEDIFF两个表基于ID多个条目

时间:2016-01-18 14:13:53

标签: sql-server-2008

我希望编写一个查询,为具有多个访问点(TOTAL_HOURS_WORKED)和多个条目(DEVICE_ID或{{}的考勤管理系统中的每位员工生成ROW_ID 1}})。

到目前为止,我认为最好的方法是获得第一个' CLOCK_IN'时间并从最后一个&CLACK_OUT'中减去它。时间;然后从中减去任何后续clockin或out的总和。以下是我迄今为止获得的数据和数据:

TIME IN LOG

TIME OUT LOG

如上所示,有许多条目,甚至一些错误或双重条目。我希望输出反映出像这样的东西

ENTRY_ID

这是我迄今为止编写的代码,它生成了上述表格:

PIN 326
TOTAL HOURS: 06:15:49 (hh:mm:ss)

1 个答案:

答案 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)