我需要根据他们的hire_date以及使用这些参数进行的评估来获取正确的查询记录:
来自system_date。
报告的工作方式是收集在当前system_date之后30天和90天之间进行评估的员工。
这是一个棘手的部分:如果hire_date比system_date大于1年,那么仅存在12个月的评估。如果他们当前的任务变化,就像他们的工作一样,他们会恢复到3个月,6个月和12个月的评估,但最终会回到12个月的评估中。
如果您需要更多说明,请与我们联系。
流程图:
答案 0 :(得分:1)
由于我不了解您的表格或您正在使用的数据库,因此我使用MS SQL Server创建了以下示例解决方案。我已声明变量,CTE(公用表表达式)并创建了一个可读性函数,但您可以轻松替换它们。
首先,我认为您有Employees
和hire_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 |
然后将计算出的evaldue_date与sysdate - 30与sysdate + 90进行比较