Reputation: 1487
I am storing employee attendance on a table 'attendance' having the following structure:
EmpID, CDate
Attendance system insert this table everyday with employee-id of all employees present on that particular day.
I need to find out absent statement of a particular employee. I can do this easily by selecting all distinct date that are not in - dates where the employee is present.
Is there any way I can remove the not in operator on that sql statement. Please help
Here is the sql query for employee with EmpId 01:
select distinct CDate
from attendance
where CDate not in (
Select CDate from attendance where EmpID='01')
Upvotes: 1
Views: 520
Reputation: 13445
The problem isn't in the NOT IN clause, it is the subquery.
You want something more like:
SELECT DISTINCT a1.CDate, if (EmpID=NULL, false,true) as Present
FROM attendance as a1
LEFT JOIN attendance as a2 USING (CDate)
WHERE a2.EmpID='01'
This is a cartesian join which pulls all of the dates, then joins the employee attendance status on that. Should be significantly faster than your subquery.
Updated, with tested code:
SELECT DISTINCT a1.CDate, IF (a2.EmpID IS NULL, false,true) as Present
FROM attendance AS a1
LEFT JOIN attendance AS a2 ON (a1.CDate = a2.CDate AND a2.EmpID='01')
My bad on the previous answer. I should have put the subselection into the ON instead of an aggregate.
Upvotes: 1
Reputation: 3078
You could change your mechanism to store data for each employee, each day. Yes, it'll add a lot of rows, but how can you be sure that you'll get all dates from logged data? what if theres nobody at work today? no one will have absense?
If you'd go with:
EmpID, CDate, Present
1, {date}, 0|1
then you'd have simpler and faster query traded for table size:
select CDate from attendance where EmpID = 1 and status = 0;
Upvotes: 1