2015-03-01 3 views
0

Я пытаюсь выполнить достаточно сложный запрос, но не могу понять, как это сделать как один запрос MySQL. давалось 3 таблицыSQL-запрос для получения последнего датированного элемента

сотрудников, офисы, employee_notes

Где сотрудники не связаны напрямую с офисами, потому что они могут двигаться офисы регулярно. Когда они перемещаются, employee_notes обновляются с новым идентификатором офиса. Таким образом, каждая строка в заметках сотрудника имеет office_id, employee_id и дату переключения. Если я хочу, чтобы получить текущий офис идентификатор данного сотрудника, я мог бы сделать:

SELECT en.office_id FROM employee_notes AS en WHERE en.employee_id = 
'userid' ORDER BY date DESC LIMIT 1; 

Однако, если я даюсь офис, то есть у меня есть office_id, и я хочу, чтобы все сотрудники, работающие на этом офис в заданную дату, я не уверен, как выполнить запрос.

Моя первая попытка что-то вроде:

SELECT emp.* FROM employees AS emp WHERE emp.id = (SELECT en.employee_id FROM employee_notes AS en WHERE en.date < 'somedate' ORDER BY date DESC LIMIT 1); 

Проблема, в приведенном выше запросе внутренний SELECT, не фильтрует employee_notes, которые имеют данный офис идентификатор. Так что я мог бы сделать:

SELECT emp.* FROM employees AS emp WHERE emp.id = (SELECT en.employee_id FROM employee_notes AS en WHERE en.date < 'somedate' AND en.office_id = 'someOfficeId' ORDER BY date DESC LIMIT 1); 

Затем внутренний запрос только выглядит в офисах, которые имеют офис идентификатор 'someOfficeId. например если сотрудник A работал в someOffice неделю назад, но затем перешел в другой офис, внутренний запрос не узнал бы этого, и весь запрос дал бы мне сотрудника A как empoyee в someOffice.

Итак, моя следующая идея состояла в том, чтобы взять вне внутреннего запроса en.office_id = 'someOfficeId'. , например.

SELECT emp.* FROM employees AS emp WHERE emp.id = (SELECT en.employee_id FROM employee_notes AS en WHERE en.date < 'somedate' ORDER BY date DESC LIMIT 1) AND en.office_id = 'someOfficeId'; 

Однако это дает ошибку MySQL, поскольку я ссылаюсь на en-alias в предложении WHERE. Я не совсем уверен, что делать дальше.

Любая помощь приветствуется.

ответ

0

Возможно, самый простой способ заключается в использовании substring_index()/group_concat() трюк, чтобы получить самую последнюю должность:

SELECT en.employee_id, 
     substring_index(group_concat(office_id order by date desc), ',', 1) as office_id 
FROM employee_notes en 
WHERE en.date < 'somedate' 
GROUP BY en.employee_id 
HAVING office_id = 'someoffice'; 

Вы также можете сделать это с помощью join и агрегации:

select en.* 
from employee_notes en join 
    (select employee_id, max(date) as maxdate 
     from employee_notes en2 
     where date < 'somedate' 
     group by employee_id 
    ) ed 
    on en.employee_id = ed.employee_id and en.date = ed.maxdate 
where en.office_id = 'someid'; 
+0

Хмм ... Это дает мне employee_notes в результате, а не сотрудников –

+0

@Caveman. , , Он дает вам 'employee_id' и' office_id'. Вы можете присоединиться к соответствующим справочным таблицам, которые вам нужны. Я отмечаю, что это согласуется с примерами, которые у вас есть в этом вопросе. –

+0

Да, вы правы. Я сделал внутреннее соединение вашего второго примера с сотрудниками, и он, похоже, работает. Благодарю. –

0

КАЖЕТСЯ Гордон попробовал более элегантное/сложное решение. Я попытался придерживаться основ ... и, надеюсь, вы можете сказать, что я имел некоторый успех.

/* how do you know, however, to which office an employee belongs if he/she had no switch whatsoever? is there an office field in the employees table ? */ 
SELECT NVL(n.office_id, e.office_id) officeId, NVL(n.employee_id, e.employee_id) employeeID 
FROM 
    /* gives the last switch per employee (employees not listed here had no switch) */ 
    (SELECT employee_id, date_of_switch 
    FROM employee_notes n 
    GROUP BY employee_id, max(date_of_switch)) m, 
    /* join with employee_notes to get the office of the last switch */ 
    employee_notes n, 
    employees e 
WHERE 
    /* if employee is not listed in M, he/she had no switch */ 
    e.employee_id = m.employee_id (+) 
AND n.switch_date = m.switch_date 
AND n.employee_id = m.employee_id 
ORDER BY 
    officeId 
+0

Caveman, дает ли это решение? – Veverke

Смежные вопросы