获取最后日期项的SQL查询

时间:2015-03-01 13:46:09

标签: mysql sql

我正在尝试执行一个相当复杂的查询,但无法弄清楚如何将其作为单个MySQL查询。 给出3个表

员工,办公室,employee_notes

员工与办公室没有直接联系,因为他们可以定期搬迁办公室。移动时,employee_notes将使用新的办公室ID进行更新。因此,员工备注中的每一行都有office_id,employee_id和切换日期。如果我想获得给定员工的当前办公室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不会过滤具有给定office id的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);

然后内部查询仅查看办公室ID为“someOfficeId”的办公室。例如如果员工A在一周之前在某个办公室工作,但后来改为另一个办公室,那么内部查询将无法识别这一点,整个查询会在一些办公室给我雇员A作为雇员。

所以,我的下一个想法是在内部查询之外采用 en.office_id ='someOfficeId'。 e.g。

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';

但是,由于我在WHERE子句中引用了别名,因此会出现MySQL错误。 我不确定下一步该尝试什么。

任何帮助表示感谢。

2 个答案:

答案 0 :(得分: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';

答案 1 :(得分: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