As mentioned by others, it will help to have a table storing all working days. For simplicity, let's say this is named business_calendar
and stores all working day dates in a DATETIME
column named working_day
. As I don't know which version of SQL Server you're using I'll use DATETIME
s throughout - so those that only represent dates will have no time part. This answer is useful to consult on how to remove the time part when making comparisons.
To err on the safe side, would suggest only querying for dates where there's no record of an employee swiping in or out - this may cater for edge cases such as the employee working beyond midnight or perhaps there might be NULL
s if for some reason one of the swipe in or swipe out didn't register.
To find the absent days for a single employee:
DECLARE @emp_id INT;
SET @emp_id = 1;
SELECT @emp_id AS employee_id, bc.working_day AS absent_day
FROM business_calendar bc
WHERE NOT EXISTS (
SELECT *
FROM attendance a
WHERE a.employee_id = @emp_id
AND (DATEADD(day, DATEDIFF(day, 0, a.swipe_in), 0) = bc.working_day
OR DATEADD(day, DATEDIFF(day, 0, a.swipe_out), 0) = bc.working_day));
...Or to get a list of all employees and dates they were absent, a CROSS JOIN
can be used:
SELECT e.id AS employee_id, bc.working_day AS absent_day
FROM business_calendar bc
CROSS JOIN employee e
WHERE NOT EXISTS (
SELECT *
FROM attendance a
WHERE a.employee_id = e.id
AND (DATEADD(day, DATEDIFF(day, 0, a.swipe_in), 0) = bc.working_day
OR DATEADD(day, DATEDIFF(day, 0, a.swipe_out), 0) = bc.working_day));
This could of course be easily filtered to only include a subset of the employees and/or dates by AND
ing further WHERE
conditions.
Demo here: http://rextester.com/VPTTM33285