高级MySQL查询在一个字段中选择和比较时间

时间:2014-09-16 16:11:02

标签: mysql sql

Employees
  EmpID : int(10)
  Firstname: varchar(100)
  Lastname: varchar(100)
  HireDate: timestamp
  TerminationDate: timestamp

  AnnualReviews
  EmpID: int(10)
  ReviewDate: timestamp

什么是返回每个员工以及每行/员工的查询包括在任期内随时为公司工作的最多员工数以及达到最大值的第一个日期。 到目前为止,这是我的疑问:

select *, (select count(empid) from employees where terminationdate between t.hiredate and t.terminationdate)
 from employees as t
 group by empid

1 个答案:

答案 0 :(得分:1)

你所拥有的是近在咫尺。

但还有更多工作要做。

我们要找出决定雇员数量和工作条件的条件。在任何时间点(即在给定的时间戳值下)。条件我检查:

HireDate <= timestamp < TerminationDate

我们需要扩展该比较,以便处理TerminationDate的NULL值,就像时间戳值之后的时间点一样。这很容易做到。)

HireDate <= timestamp AND ( timestamp < TerminationDate OR TerminationDate IS NULL

所以,像这样:

 SELECT COUNT(1)
   FROM Employees e
  WHERE ( :timestamp >= e.HireDate )
    AND ( :timestamp <  e.TerminationDate OR e.TerminationDate IS NULL)

那&#34;计数&#34;价值将保持不变,并且只会因为雇佣而被改变。或者&#34;终止&#34;事件

如果我们得到所有时间戳的明确列表,那么#34;雇用&#34;并且&#34;终止&#34;事件,我们可以获得当时的员工数量。

因此,每次员工数量可能发生变化时,此查询都会向我们提供员工数量:

 SELECT t.ts     AS `as_of`
      , COUNT(1) AS `employee_count`
   FROM Employees e
   JOIN ( SELECT t.TerminationDate AS ts
            FROM Employees t
           WHERE t.TerminationDate IS NOT NULL
           GROUP BY t.TerminationDate
           UNION
          SELECT h.HireDate AS ts
            FROM Employees h
           WHERE h.HireDate IS NOT NULL
           GROUP BY h.HireDate
        ) t
     ON ( t.ts >= e.HireDate )
    AND ( t.ts <  e.TerminationDate OR e.TerminationDate IS NULL)
  GROUP BY t.ts

我们可以使用该结果(作为内联视图)并将其加入特定的Employee,并获得具有as_of时间戳的行,该时间戳与该员工的就业期相匹配。然后拔出最大employee_count。如果最多as_of次出现多次,则很难确定多个employee_count日期的早期日期。

(问题的措辞留下了一个问题,即最早的日期&#34; 永远员工数量达到或超过员工任期内发生的最大值,或者只是员工任期内最早达到最高限额的日期。可以得到任何结果。)

这只是解决问题的一种方法。