Reputation: 5842
I have table (ATTENDANCE) contains the attendance of the employee as following
EMPNO DATE
2 07/11/2016
2 07/12/2016
3 07/12/2016
6 07/13/2016
7 07/13/2016
which contains the employee number(empno) and the attended date(date)
And another table (EMPLOYEES) contains all the empolyees in the company for example like this
EMPNO NAME
1 Musa
2 Ali
3 Khalid
6 James
7 Sara
I can find if an employee was absent in a specific date by using this code
select empno
from EMPLOYEES
where empno not in (select empno
from ATTENDANCE
where date = '07/11/2016')
I want to retreive the list of absent employees in any day between a specific range
I tried to use this query
select empno
from EMPLOYEES
where empno not in (select empno
from ATTENDANCE
where date between '07/11/2016' and '07/13/2016' )
but this will give me those who are absent in all the days in this range , If an employee was absent in one day only it will not retreive it
I want a query to retreive the empno and the date where the employee was absent?
Update: I tried this too , as sagi mentioned
select empno
from EMPLOYEES
where empno not in (select empno
from ATTENDANCE
group by empno
having count(empno) = to_date(' 07/09/2016','mm,dd,rrrr') - to_date('07/13/2016','mm,dd,rrrr') )
this will work but it will not give me in which date the employee was absent
Upvotes: 2
Views: 2084
Reputation: 19
A much cleaner approach here would be to use a CTE to identify all distinct days in the attendance table.
we then do a Cross join with employees table to get all possible combinations
Finally we will check the existence of the EmpNo, Date tuple in the Attendance table.
With Dates (date) as (Select Distinct Date from Attendance )
Select Emp.EmpNo, dates.date from employee emp cross join Dates
where (emp.empno, dates.date) not in
(Select Empno, date from Attendance
Upvotes: 0
Reputation: 36087
I want a query to retreive the empno and the date where the employee was absent
In such a case you need to generate all possible dates in a given range using for example this query:
SELECT date '2016-07-11' + level - 1 As "DATE" from dual
CONNECT BY LEVEL <= date '2016-07-13' - date '2016-07-11' + 1;
DATE
-----------------
16/07/11 00:00:00
16/07/12 00:00:00
16/07/13 00:00:00
then use a cross join to generate all possible pairs: date+employe
SELECT e.empno, d."DATE"
FROM (
SELECT date '2016-07-11' + level - 1 As "DATE" from dual
CONNECT BY LEVEL <= date '2016-07-13' - date '2016-07-11' + 1
) d
CROSS JOIN empno e
and then filter existing records out (leaving only not existing pairs: empno+date) using an outer join and IS NULL condition
SELECT e.empno, d."DATE"
FROM (
SELECT date '2016-07-11' + level - 1 As "DATE" from dual
CONNECT BY LEVEL <= date '2016-07-13' - date '2016-07-11' + 1
) d
CROSS JOIN EMPLOYEES e
LEFT JOIN ATTENDANCE a
ON ( a.empno = e.empno AND a."DATE" = d."DATE" )
WHERE a."DATE" IS NULL
order by 1,2
Upvotes: 2
Reputation: 19
select distinct empno from EMPLOYEES e, left join ATTENDANCE a on e.empno = a.empno and e.date=a.date where a.empno is NULL
Upvotes: 0