【问题标题】:How to pull the latest or minimum start date, based on the break-up in continuation of the start date and end date of the records using SQL query如何根据使用 SQL 查询的记录的开始日期和结束日期的连续中断来提取最新或最小开始日期
【发布时间】:2022-10-13 01:00:41
【问题描述】:

请帮助我创建一个 sql 查询,以使用以下条件提取员工的最小或最新开始日期。

  1. 如果记录的开始日期和结束日期的连续性没有中断,则通过最短开始日期。
  2. 如果在之前和当前记录的结束日期和开始日期之间的 30 天内分手,则通过最短开始日期
  3. 如果之前和当前记录的结束日期和开始日期之间的分手时间超过 30 天,则超过最晚开始日期。

    例子: 下面是数据表

    EmpID   ProdID  HireStartDt HireEndDate
    98765   X123    08/01/2020  12/31/2020
    98765   X123    01/01/2021  12/31/2021
    98765   X123    01/01/2022  12/31/2022
    43567   X123    01/01/2021  12/31/2021
    43567   X123    01/29/2022  12/31/2022
    65427   X123    05/06/2021  08/28/2021
    65427   X123    03/01/2022  12/31/2022
    

    对于 EmpID : 98765,我们需要将最小开始日期传递为 '08/01/2020',因为记录之间的 startDt 和 End Dt 的延续没有中断。

    对于 EmpID : 43567,我们需要将最小开始日期传递为 '01/01/2021',因为上一个记录的 EndDt 和当前记录的 startDt 之间的分手时间少于 30 天。

    对于 EmpID : 65427,我们需要将最晚开始日期传递为 '03/01/2022',因为之前记录的 EndDt 和当前记录的 startDt 之间的间隔大于 30 天。

    预期结果:

    EmpID   ProdID  HireStartDt HireEndDate
    98765   X123    08/01/2020  12/31/2020
    43567   X123    01/01/2021  12/31/2021
    65427   X123    03/01/2022  12/31/2022
    

    请帮我 !!

    谢谢 戈帕尔

【问题讨论】:

  • 我不清楚如果有多个条目会发生什么,但有些是连续的,有些不是,例如 (1, 'X123' , '08/01/2020','10/31/2020'), (1, 'X123' , '01/01/2021','12/31/2021'), (1, 'X123', '01/01/2022', '12/31/2022');
  • 对于连续记录,我们需要通过最小开始日期,而对于终止记录,我们需要检查上一个记录的结束日期和当前记录的开始日期之间的日期差异,如果差异小于 30 天,那么我们可以通过最小开始日期,否则我们需要传递最新的开始日期。希望能帮助到你..
  • 您的最后一条评论只是重复了这个问题,并没有帮助。在您的样本中,您有 2 个数据不连续的案例,但在我的示例中只有 2 行,第一行和第二行不连续,但 2 和第三行不连续

标签: mysql sql tsql


【解决方案1】:

在您的示例输出中,您显示的结束日期与所选的开始日期位于同一记录中。但是,您似乎实际上想要最新的结束日期,它们都是 2022 年 12 月 31 日。如果这是正确的,下面的代码应该适合你。

但是,如果结束日期需要来自与所选开始日期相同的记录,则此代码不会产生该结果。如果需要,该查询同样易于生成。

查询输出在代码下方给出。

IF OBJECT_ID('tempdb..#EmployeeCoverage') IS NOT NULL
    DROP TABLE #EmployeeCoverage;

CREATE TABLE #EmployeeCoverage
(
    EmpID INT
    , ProdID VARCHAR(4)
    , HireStartDt DATE
    , HireEndDt DATE
);

INSERT INTO #EmployeeCoverage
    (EmpID, ProdID, HireStartDt, HireEndDt)
VALUES
    (98765, 'X123', '2020-08-01', '2020-12-31'),
    (98765, 'X123', '2021-01-01', '2021-12-31'),
    (98765, 'X123', '2022-01-01', '2022-12-31'),
    (43567, 'X123', '2021-01-01', '2021-12-31'),
    (43567, 'X123', '2022-01-29', '2022-12-31'),
    (65427, 'X123', '2021-05-06', '2021-08-28'),
    (65427, 'X123', '2022-03-01', '2022-12-31');


IF OBJECT_ID('tempdb..#EmployeeCoverageGaps') IS NOT NULL
    DROP TABLE #EmployeeCoverageGaps;

CREATE TABLE #EmployeeCoverageGaps
(
    EmpID INT
    , ProdID VARCHAR(4)
    , HireStartDt DATE
    , HireEndDt DATE
    , GapDays INT -- Possibly SMALLINT
);

INSERT INTO #EmployeeCoverageGaps
    (EmpID, ProdID, HireStartDt, HireEndDt, GapDays)
SELECT
    EmpID, ProdID, HireStartDt, HireEndDt
    -- Get the days between the current end date and the next start date
    , ISNULL(DATEDIFF(DAY, HireEndDt, LEAD(HireStartDt) OVER
        (PARTITION BY EmpID, ProdID ORDER BY HireStartDt)), 0) AS GapDays
FROM
    #EmployeeCoverage;

SELECT
    EmpID
    , ProdID
    , MIN(HireStartDt) AS HireStartDt
    , MAX(HireEndDt) AS HireEndDt
FROM #EmployeeCoverageGaps
WHERE GapDays < 30 -- Remove start/end ranges with gaps more than 30 days
GROUP BY EmpID, ProdID
EmpID ProdID HireStartDt HireEndDt
43567 X123 2021-01-01 2022-12-31
65427 X123 2022-03-01 2022-12-31
98765 X123 2020-08-01 2022-12-31

【讨论】: