Reputation: 3760
I have a table employee
having columns id (primary key), *employee_name* and another table called employee_works
with columns *employee_id* (foreign key referencing employee.id), *start_date* (datetime), *finish_date* (datetime).
Here are some datas for employee table:
**id** **employee_name**
1 employee A
2 employee B
3 employee C
4 employee D
5 employee E
6 employee F
7 employee G
employee_works table:
1 2010-01-01 00:00:00 NULL
2 2010-01-01 00:00:00 2010-01-10 10:00:00"
2 2010-01-13 00:00:00 2010-01-15 10:00:00"
2 2010-01-31 00:00:00 NULL
4 2010-02-18 00:00:00 2011-01-31 00:00:00"
6 2010-02-18 00:00:00 NULL
NULL value means the employee still works. I need to get a single query showing the list of persons in employee, if they worked with us, who still works in our company, who left and if possible, for how long they worked with us. Example:
id employee_name status
1 Employee A Still with us
3 Employee C Never worked
4 Employee D Left
My attempt:
SELECT emp.id,emp.name,
CASE
WHEN occ.finish_date is NULL and occ.start_date is NOT NULL THEN 'Still working'
WHEN occ.finish_date is NULL and occ.start_date is NULL THEN 'Never Worked'
WHEN occ.finish_date is NOT NULL and occ.start_date is NOT NULL THEN 'Left'
END
AS status
FROM employee AS emp
LEFT JOIN employee_works AS occ ON emp.id=occ.employee_id
GROUP BY emp.id, occ.finish_date
I also want to get the total no of days the employees have worked in another column?
Upvotes: 1
Views: 131
Reputation: 1269543
The problem is that you have a group by but no aggregations for the definition of status. Mysql does not give you a syntax error. Instead, it gives you a random status:
Try something like this instead:
select id, name,
(CASE WHEN statusint = 3
THEN 'Still working'
WHEN statusint = 1 or statusint is null
THEN 'Never Worked'
WHEN statusint = 2
THEN 'Left'
END) AS status,
days_worked
from (SELECT emp.id, emp.name,
max(CASE WHEN occ.departure_date is NULL and occ.start_date is NOT NULL
THEN 3
WHEN occ.departure_date is NULL and occ.start_date is NULL
THEN 1
WHEN occ.departure_date is NOT NULL and occ.start_date is NOT NULL
THEN 2
END) AS statusint,
sum(datediff(coalesce(departure_date, curdate()), occ.start_date
) as days_worked
FROM employee emp LEFT JOIN
employee_works occ
ON emp.id=occ.employee_id
GROUP BY emp.id, emp.name
) eg
This "feature" of mysql is called hidden columns. Folks who write mysql (and many who use it) think this is a great feature. Many people who use other databases just scratch their heads and wonder why any database would act so strangely.
By the way, you should check if someone who is employeed multiple times gets assigned a new id. If so, your query might need more advanced name matching methods.
Upvotes: 1
Reputation: 263693
Try to simplify your condition.
SELECT a.*,
CASE
WHEN b.employeeID IS NULL THEN 'NEVER WORKED'
WHEN b.finish_date IS NULL THEN 'STILL WORKING'
WHEN DATE(b.finish_date) < CURDATE() THEN 'LEFT'
END as `Status`
FROM employee a
LEFT JOIN employee_works b
on a.id = b.employeeID
Upvotes: 0