【问题标题】:Finding original start date to absence period查找原始开始日期到缺勤期
【发布时间】:2017-09-15 10:49:15
【问题描述】:

你能看看下面的任务吗?

我有 DATA 表(它包含上一周的数据):

CREATE TABLE DATA
(
EMPLOYEE nvarchar(50),
ABSENCE_START_DATE datetime,
ABSENCE_END_DATE datetime,
ABSENCE_TYPE nvarchar(50)
)

ABSENCE_START_DATE - date when absence starts
ABSENCE_END_DATE  - date when absence ends
ABSENCE_TYPE - type of absence

当前表包含以下数据:

INSERT INTO DATA(EMPLOYEE,ABSENCE_START_DATE,ABSENCE_END_DATE,ABSENCE_TYPE) VALUES
('EMP01','2017-09-04 00:00:00.000','2017-09-06 00:00:00.000','Sickness'),--Monday - Wednesday
('EMP01','2017-09-08 00:00:00.000','2017-09-08 00:00:00.000','Vacation'),--Friday - Friday
('EMP02','2017-09-04 00:00:00.000','2017-09-09 00:00:00.000','Sickness'),--Monday - Friday
('EMP03','2017-09-05 00:00:00.000','2017-09-09 00:00:00.000','Sickness')--Tuesday - Friday

另外,我还有另一个表 - STORAGE(它包含早于前一周开始的日期的数据)。

CREATE TABLE STORAGE
(
EMPLOYEE nvarchar(50),
APPLY_DATE datetime,
ABSENCE_TYPE nvarchar(50)
)

有每日记录(不包括周六和周日——它们永远不会存在于这个表中)

INSERT INTO STORAGE(EMPLOYEE,APPLY_DATE,ABSENCE_TYPE) VALUES
('EMP01','2017-08-27 00:00:00.000','Sickness'),
('EMP01','2017-08-28 00:00:00.000','Worked'),
('EMP01','2017-08-29 00:00:00.000','Worked'),
('EMP01','2017-08-30 00:00:00.000','Sickness'),
('EMP01','2017-08-31 00:00:00.000','Sickness'),
('EMP01','2017-09-01 00:00:00.000','Sickness'),
('EMP02','2017-08-31 00:00:00.000','Worked'),
('EMP02','2017-09-01 00:00:00.000','Sickness')

所以,任务是: sql -script 应该找到缺勤期间的原始开始日期(来自 DATA 表),缺勤开始日期是 星期一

换句话说,脚本应该日复一日地“过去”并找到适当的缺勤期开始的日期。

星期一缺勤不一定是“生病”。也可以是“旅行”、“孕产”……

以下示例的预期结果是(注意第一行和第三行 - 缺勤开始日期与 DATA 表中的相应行不同):

提前谢谢你。

【问题讨论】:

  • 在 STORAGE 中,EMP01 于 2017 年 8 月 29 日工作,但您的预期结果显示这是他们缺席的开始。对吗?
  • 为什么absence_start_date = 2017-08-29emp01 的结果中是根据他在同一日期工作的storage 表?如果是emp03,它正确吗?反之亦然?
  • 是的,对不起,你们是对的。我的错
  • 我修改了下面的“预期”结果部分屏幕

标签: sql sql-server sql-server-2012


【解决方案1】:

从共享的示例数据来看,您似乎希望从storageabsence_start_date 列的data 表中检索min date,下面的查询可以是一个选项。

SELECT d.Employee,
       coalesce(CASE
                    WHEN d.ABSENCE_TYPE = 'Sickness' THEN
                           (SELECT min(apply_date)
                            FROM
                            STORAGE s
                            WHERE s.employee = d.employee
                              AND s.ABSENCE_TYPE = 'Sickness')
                    ELSE d.ABSENCE_START_DATE
                END,d.ABSENCE_START_DATE) AS ABSENCE_START_DATE,
       d.ABSENCE_END_DATE,
       ABSENCE_TYPE
FROM DATA d;

更新 1: 下面是一个更通用的查询。

SELECT d.Employee,
       coalesce(
                  (SELECT min(apply_date)
                   FROM
                   STORAGE s
                   WHERE s.employee = d.employee
                     AND s.ABSENCE_TYPE = d.ABSENCE_TYPE),d.ABSENCE_START_DATE) AS ABSENCE_START_DATE,
       d.ABSENCE_END_DATE,
       d.ABSENCE_TYPE
FROM DATA d

更新 2: 如果你想从数据中排除weekends,下面是查询。

SELECT d.Employee,
       coalesce(
                  (SELECT min(apply_date)
                   FROM
                   STORAGE s
                   WHERE s.employee = d.employee
                     AND s.ABSENCE_TYPE = d.ABSENCE_TYPE
                     AND DATENAME(dw,apply_date) NOT IN('Sunday','Saturday')),d.ABSENCE_START_DATE) AS ABSENCE_START_DATE,
       d.ABSENCE_END_DATE,
       d.ABSENCE_TYPE
FROM DATA d

结果:

Employee    ABSENCE_START_DATE      ABSENCE_END_DATE    ABSENCE_TYPE
--------------------------------------------------------------------
EMP01       30.08.2017 00:00:00    06.09.2017 00:00:00    Sickness
EMP01       08.09.2017 00:00:00    08.09.2017 00:00:00    Vacation
EMP02       01.09.2017 00:00:00    09.09.2017 00:00:00    Sickness
EMP03       05.09.2017 00:00:00    09.09.2017 00:00:00    Sickness

您可以查看演示here

希望这会有所帮助。

【讨论】:

  • 嗨,扎鲁克,非常感谢。是的,它有效,但在您的代码中,您有以下过滤器“ABSENCE_TYPE = 'Sickness'”,但周一可能有其他缺勤类型。例如。 'Travel'、'Maternity'...所以,在这种情况下,代码将不起作用。
  • Zarruq,我不需要找到从存储到数据表的缺席开始日期列的最小日期。例如。在 Storage 员工 EMP01 具有以下数据: EMP01 2017-08-28 Sickness EMP01 2017-08-29 Worked EMP01 2017-08-30 Sickness EMP01 2017-08-31 Sickness 因此,您的代码将找到 8 月 28 日作为缺勤开始,但必须是 8 月 30 日
  • @DavidFreeman:更新您的问题。我会更新我的答案。我假设提供的数据有限。根据您当前的示例数据,我的查询有效。
  • @DavidFreeman:检查更新的答案。我添加了一个更通用的查询。
  • Zarruq,如果 STORAGE 包含以下数据: EMP01 2017-08-27 00:00:00.000 Sickness EMP01 2017-08-28 00:00:00.000 Worked EMP01 2017-08-29 00:00 :00.000 工作 EMP01 2017-08-30 00:00:00.000 疾病 EMP01 2017-08-31 00:00:00.000 疾病 EMP01 2017-09-01 00:00:00.000 疾病
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多