将您的打卡日期表视为:
emp_punch_time (empno, punch_time)
该表只存储empno(即员工编号)和punch_time(包括日期和时间)。
在这种情况下,您可以执行以下操作:
WITH emp_punch_time AS (
-- This common table expression is just for your illustration.
-- When using this query on your base tables remove this CTE and make
-- appropriate changes to the subsequent queries.
SELECT 7369 AS empno
, TO_DATE('29-JUN-2013 22:00:00', 'DD-MON-YYYY HH24:MI:SS') punch_time
FROM dual
UNION
SELECT 7369, TO_DATE('30-JUN-2013 07:00:00', 'DD-MON-YYYY HH24:MI:SS') FROM dual
UNION
SELECT 7369, TO_DATE('30-JUN-2013 15:00:00', 'DD-MON-YYYY HH24:MI:SS') FROM dual
UNION
SELECT 7369, TO_DATE('30-JUN-2013 22:30:00', 'DD-MON-YYYY HH24:MI:SS') FROM dual
UNION
SELECT 7370, TO_DATE('29-JUN-2013 07:00:00', 'DD-MON-YYYY HH24:MI:SS') FROM dual
UNION
SELECT 7370, TO_DATE('29-JUN-2013 15:00:00', 'DD-MON-YYYY HH24:MI:SS') FROM dual
UNION
SELECT 7370, TO_DATE('29-JUN-2013 22:00:00', 'DD-MON-YYYY HH24:MI:SS') FROM dual
UNION
SELECT 7370, TO_DATE('30-JUN-2013 07:00:00', 'DD-MON-YYYY HH24:MI:SS') FROM dual
)
, punch AS (
SELECT p.empno
, p.punch_time
, CASE MOD(row_number() over (partition by empno
order by p.punch_time asc), 2)
WHEN 1 THEN 'IN'
ELSE 'OUT'
END AS punch_type
FROM emp_punch_time p)
, punch_repo AS (
SELECT p.empno
, p.punch_time AS in_time
, (SELECT punch_time
FROM punch p_out
WHERE p_out.punch_type = 'OUT'
AND p_out.empno = p.empno
AND p_out.punch_time = (SELECT MIN(punch_time)
FROM punch p_min
WHERE p_min.punch_type = 'OUT'
AND p_min.empno = p_out.empno
AND p_min.punch_time > p.punch_time))
AS out_time
FROM punch p
WHERE punch_type = 'IN'
)
SELECT empno
, TO_CHAR(in_time, 'DD-MON-YYYY HH24:MI:SS') in_time
, TO_CHAR(out_time, 'DD-MON-YYYY HH24:MI:SS') out_time
, TRIM(TO_CHAR(FLOOR((out_time - in_time) * 24), '09'))
||':'
|| TRIM(TO_CHAR(FLOOR(MOD((out_time - in_time)*24, 1) * 60), '09'))
AS time_spent
FROM punch_repo
;
输出
EMPNO IN_TIME OUT_TIME TIME_SPENT
7369 29-JUN-2013 22:00:00 30-JUN-2013 07:00:00 09:00
7369 30-JUN-2013 15:00:00 30-JUN-2013 22:30:00 07:30
7370 29-JUN-2013 07:00:00 29-JUN-2013 15:00:00 08:00
7370 29-JUN-2013 22:00:00 30-JUN-2013 07:00:00 09:00