创建3个月,6个月和12个月的评估查询

时间:2014-09-19 15:38:08

标签: sql

我需要根据他们的hire_date以及使用这些参数进行的评估来获取正确的查询记录:

  • 3个月
  • 6个月
  • 12个月

来自system_date。

报告的工作方式是收集在当前system_date之后30天和90天之间进行评估的员工。

这是一个棘手的部分:如果hire_date比system_date大于1年,那么仅存在12个月的评估。如果他们当前的任务变化,就像他们的工作一样,他们会恢复到3个月,6个月和12个月的评估,但最终会回到12个月的评估中。

如果您需要更多说明,请与我们联系。

流程图

flow-chart

2 个答案:

答案 0 :(得分:1)

由于我不了解您的表格或您正在使用的数据库,因此我使用MS SQL Server创建了以下示例解决方案。我已声明变量,CTE(公用表表达式)并创建了一个可读性函数,但您可以轻松替换它们。

SQL Fiddle demo

首先,我认为您有Employeeshire_date的简单last_assignment_change表格。

我已插入一些样本数据进行测试:

员工

| ID |  NAME |  HIRE_DATE | LAST_ASSIGNMENT_CHANGE | 
|----|-------|------------|------------------------|
|  1 | Alice | 2012-07-15 |                 (null) | 
|  2 |   Bob | 2013-12-02 |                 (null) |
|  3 | Carol | 2014-01-13 |                 (null) |
|  4 |  Dave | 2014-01-13 |             2014-08-28 |
|  5 |   Eve | 2014-03-15 |                 (null) |
|  6 | Frank | 2014-06-15 |                 (null) |
|  7 |  Gina | 2014-09-15 |                 (null) |


所以,我们有:

Today = 2014-09-25  
Filter dates between 2014-08-25 and 2014-12-25

Alice: next evaluation = 2014-07-15 -> do not show
Bob:   next evaluation = 2014-12-02 -> show
Carol: next evaluation = 2015-01-13 -> do not show
Dave:  next evaluation = 2014-11-28 -> show
Eve:   next evaluation = 2014-09-15 -> show
Frank: next evaluation = 2014-09-15 -> show
Gina:  next evaluation = 2014-12-15 -> show


接下来,我创建了一个函数来简化在查询结束时使用的CAST到DATE:

CREATE FUNCTION dbo.fn_CastDate
                 ( @year int, @month int, @day int )
RETURNS date
AS
BEGIN
  RETURN
    CAST(
        CAST(@year AS VARCHAR(4)) +
        RIGHT('0' + CAST(@month AS VARCHAR(2)), 2) +
        RIGHT('0' + CAST(@day AS VARCHAR(2)), 2) 
     AS DATE)
END
GO


最后,按评估日期筛选的查询:

BEGIN
  DECLARE
    @today date, 
    @last_month date,
    @next_three_months date    

  SET @today = CAST(GETDATE() AS DATE)
  SET @last_month = DATEADD(month, -1, @today)
  SET @next_three_months = DATEADD(month, 3, @today)

  ;WITH employees_cte AS
  (
    SELECT
      id,
      name,
      COALESCE(last_assignment_change, hire_date) AS assignment_date -- if last_assignment_change is null, use hire_date
    FROM
      employees
  )
  SELECT
    *
  FROM
    employees_cte
  WHERE
    DATEADD(month, 3, assignment_date) BETWEEN @last_month AND @next_three_months -- Evaluation = 3 months
    OR
    DATEADD(month, 6, assignment_date) BETWEEN @last_month AND @next_three_months -- Evaluation = 6 months
    OR
    DATEADD(month, 12, assignment_date) BETWEEN @last_month AND @next_three_months -- Evaluation = 12 months
    OR
    (DATEDIFF(day, assignment_date, @next_three_months) < 365 -- Evaluation = annual
      AND
         (dbo.fn_CastDate(YEAR(@last_month), MONTH(assignment_date), DAY(assignment_date)) -- test with YEAR(@last_month)
               BETWEEN @last_month AND @next_three_months
           OR

          dbo.fn_CastDate(YEAR(@next_three_months), MONTH(assignment_date), DAY(assignment_date)) -- test with YEAR(@next_three_months)
               BETWEEN @last_month AND @next_three_months)
    )

END


输出:

| ID |  NAME | ASSIGNMENT_DATE |
|----|-------|-----------------|
|  2 |   Bob |      2013-12-02 |
|  4 |  Dave |      2014-08-28 |
|  5 |   Eve |      2014-03-15 |
|  6 | Frank |      2014-06-15 |
|  7 |  Gina |      2014-09-15 |


注意:如果您尝试将2012-02-29(闰年)等日期转换为2014-02-29(不是闰年),则CastDate函数将失败。要解决此问题,请在使用CAST之前将February 29转换为February 28

答案 1 :(得分:1)

注意:我认为Oracle是dbms,因为你指的是sysdate。

如果有一组提供的样本数据和预期结果,对所有相关人员来说会更简单。 但是,使用这些数据(源自Zanon希望你不介意):

| ID |  NAME |  HIRE_DATE | ISCONTRACTOR | TERM_DATE |
|----|-------|------------|--------------|-----------|
|  1 | Alice | 2012-07-15 |            0 |    (null) |
|  2 |   Bob | 2013-12-02 |            0 |    (null) |
|  3 | Carol | 2014-01-13 |            1 |    (null) |
|  4 |  Dave | 2014-01-13 |            0 |    (null) |
|  5 |   Eve | 2014-03-15 |            0 |    (null) |
|  6 | Frank | 2014-06-15 |            0 |    (null) |
|  7 |  Gina | 2014-09-15 |            0 |    (null) |

和这个查询:

select
        id
      , name
      , to_char(hire_date,'yyyy-mm-dd') hire_date
      , to_char(anniversary,'yyyy-mm-dd') anniversary
      , case when evaldue = 3  then to_char(add_months(hire_date,3) ,'yyyy-mm-dd')
             when evaldue = 6  then to_char(add_months(hire_date,6) ,'yyyy-mm-dd')
             when evaldue = 9  then to_char(add_months(hire_date,9) ,'yyyy-mm-dd')
             when evaldue = 12 then to_char(anniversary,'yyyy-mm-dd') 
        end evaldue_date
      , evaldue
FROM (
      select
            employees.*
          , case
                 when add_months(hire_date,3)  > trunc(sysdate) then 3 
                 when add_months(hire_date,6)  > trunc(sysdate) then 6 
                 when add_months(hire_date,9)  > trunc(sysdate) then 9 
                 else 12 
            end evaldue
          , to_date(to_char(sysdate,'YYYY') || to_char(hire_date,'MMDD'),'YYYYMMDD') anniversary
      from employees
      where iscontractor = 0 -- i.e. only for employees
      and term_date IS NULL
      )
WHERE
        case when evaldue = 3  then add_months(hire_date,3)
             when evaldue = 6  then add_months(hire_date,6)
             when evaldue = 9  then add_months(hire_date,9)
             when evaldue = 12 then anniversary
        end between trunc(sysdate) - 30 and trunc(sysdate) + 90
ORDER BY
      evaldue_date ASC
    , evaldue ASC
;

这是计算结果:

| ID |  NAME |  HIRE_DATE | ANNIVERSARY | EVALDUE_DATE | EVALDUE |
|----|-------|------------|-------------|--------------|---------|
|  4 |  Dave | 2014-01-13 |  2014-01-13 |   2014-10-13 |       9 |
|  2 |   Bob | 2013-12-02 |  2014-12-02 |   2014-12-02 |      12 |
|  7 |  Gina | 2014-09-15 |  2014-09-15 |   2014-12-15 |       3 |
|  6 | Frank | 2014-06-15 |  2014-06-15 |   2014-12-15 |       6 |
|  5 |   Eve | 2014-03-15 |  2014-03-15 |   2014-12-15 |       9 |
  • 根据hire_date计算出3,6或9的“evaldue”(即哪个 如果hire_date超过9个月,则需要进行绩效评估 evaldue是12。
  • hire_date周年纪念日也计算以供日后参考
  • 使用先前的计算计算evaldue_date
  • 然后将计算出的evaldue_date与sysdate - 30与sysdate + 90进行比较

    See this demonstrated at SQLFiddle