7

我最近的任务是找出工作日期之间的差距,其中差距被定义为从一份工作结束到下一份工作开始的时间跨度大于 30 天,并且能够提出一个查询适合,见下文:

WITH GapsInEmployment AS
(
    SELECT 
    -1 AS DriverQualificationApplicationEmploymentGapId
    ,E1.DriverQualificationApplicationId
    ,E1.EndDate AS EmploymentGapBeginDate
    ,E2.StartDate AS EmploymentGapEndDate
    ,(
        CASE 
            WHEN ISNULL(DATEDIFF(DD, E1.EndDate, E2.StartDate), 0) < 0 THEN 0
            ELSE DATEDIFF(DD, E1.EndDate, E2.StartDate)
        END
        ) AS DaysLapsedBetweenEmployment
        ,NULL AS ReasonForEmploymentGap
    FROM @EmploymentGapInfo E1
    LEFT JOIN @EmploymentGapInfo E2 
        ON E1.RowNum = E2.RowNum - 1
)

SELECT *
FROM GapsInEmployment
WHERE DaysLapsedBetweenEmployment > 30;

我正在将一条记录与下一条记录进行比较,以查看第一条记录的结束日期和第二条记录的开始日期之间是否有 30 天的间隔,这对于“正常”情况下工作正常,即工作期间不重叠的地方。好吧,这种特殊情况已经出现,即某人在特定时间段内拥有一份以上的工作,而工作 A 的时间段介于员工拥有工作 B 的时间段之间。这是使用上述查询运行的测试数据:

DECLARE @EmploymentGapInfo TABLE
(
    RowNum INT IDENTITY(1, 1)
    ,DriverQualificationApplicationEmploymentId INT
    ,DriverQualificationApplicationId INT
    ,StartDate DATETIME
    ,EndDate DATETIME
);
INSERT INTO @EmploymentGapInfo
SELECT -1, 766, '10/14/2003', '11/07/2003';

INSERT INTO @EmploymentGapInfo
SELECT -1, 766, '08/28/2006', '06/15/2011';

INSERT INTO @EmploymentGapInfo
SELECT -1, 766, '08/22/2011', '10/23/2012';

INSERT INTO @EmploymentGapInfo
SELECT -1, 766, '06/01/2012', '07/01/2012';

INSERT INTO @EmploymentGapInfo
SELECT -1, 766, '11/01/2012', '03/05/2013';

INSERT INTO @EmploymentGapInfo
SELECT -1, 766, '10/14/2013', NULL;

如果您运行查询,它会错误地计算 07/01/2012 和 11/01/2012 之间的就业差距,这是不正确的,因为该记录的开始日期和结束日期在前一个记录之间开始。查询应为间隙生成以下结果集:

2003 年 11 月 7 日 -> 2006 年 8 月 28 日

2011 年 6 月 15 日 -> 2011 年 8 月 22 日

2013 年 3 月 5 日 -> 2013 年 10 月 14 日

我的问题是,我试图想出一种方法来在没有游标的情况下正确计算它,因为我一直在尝试的方式将涉及我循环遍历 EmploymentGapInfo 表变量中的每条记录,并且一旦我开始和该记录的结束日期,再次遍历表以查看开始日期和结束日期是否与表中的任何其他记录重叠。

有什么方法可以使用基于集合的方法而不是尝试使用游标来解决这个问题?这会是一个在业务层完成而不是在数据库中解决的问题吗?

任何帮助,将不胜感激。

4

3 回答 3

7

适用于 sql server 2012 及更高版本的绝佳解决方案。所有的功劳都归功于 A Boucher 询问汤姆https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:529176000346581356

select *
from (
      select 
       max(enddate) over (order by startdate) start_range
       ,lead(startdate) over (order by startdate) end_range
      from @EmploymentGapInfo
    ) as c
where c.start_range < c.end_range
于 2014-10-29T03:04:33.480 回答
0

您可以创建一个临时表,其中包含按日期升序排列的@EmploymentGapInfo 的所有日期。之后更容易找出差距。

获取所有日期的查询可能如下所示:

select distinct StartDate 'GDate'
from @EmploymentGapInfo
union
select distinct EndDate 
from @EmploymentGapInfo
于 2013-10-14T17:39:23.820 回答
0

也许是旧帖子......但这是答案:

首先,您应该消除具有重叠范围的可能性,并将结果表示在非重叠范围列表中。这不是一件容易的事,您可以使用以下查询来完成:

    SELECT *
    INTO #TEMP
    FROM
    (
          SELECT DriverQualificationApplicationEmploymentId, DriverQualificationApplicationId, Min(NewStartDate) StartDate, MAX(EndDate) EndDate
          FROM
          (
                SELECT DriverQualificationApplicationEmploymentId, DriverQualificationApplicationId, StartDate, EndDate,
                      NewStartDate = Range_UNTIL_NULL.StartDate + NUMBERS.number,
                      NewStartDateGroup =     DATEADD(d, 
                                                  1 - DENSE_RANK() OVER (PARTITION BY DriverQualificationApplicationEmploymentId, DriverQualificationApplicationId ORDER BY Range_UNTIL_NULL.StartDate + NUMBERS.number), 
                                                  Range_UNTIL_NULL.StartDate + NUMBERS.number)
                FROM 
                (
                      SELECT 
                            DriverQualificationApplicationEmploymentId, DriverQualificationApplicationId, StartDate, ISNULL(EndDate, dateadd(d,1,StartDate)) AS EndDate
                      FROM @EmploymentGapInfo T1
                      WHERE
                            NOT  EXISTS (   SELECT * 
                                            FROM @EmploymentGapInfo t2 
                                            WHERE  T1.DriverQualificationApplicationEmploymentId = t2.DriverQualificationApplicationEmploymentId AND
                                                   T1.DriverQualificationApplicationId = T2.DriverQualificationApplicationId and 
                                                   T1.StartDate > T2.StartDate AND T2.EndDate IS NULL
                                        )
                )  AS Range_UNTIL_NULL
                CROSS APPLY  Enumerate ( ABS(DATEDIFF(d, StartDate, EndDate))) AS NUMBERS
                      ) X
          GROUP BY DriverQualificationApplicationEmploymentId, DriverQualificationApplicationId, NewStartDateGroup
    ) OVERLAPED_RANGES_WITH_COUNT
    ORDER BY DriverQualificationApplicationEmploymentId, DriverQualificationApplicationId, StartDate    

然后您可以计算超过 30 天的差距:

SELECT 
    EndDate AS StartGap, 
    ( SELECT MIN(StartDate) FROM #temp t3 WHERE t3.startdate  > t1.endDate) AS EndGap 
FROM #TEMP t1
WHERE EndDate + 30 < (SELECT Min(startDate) FROM #temp t2 WHERE t2.startdate  > t1.endDate) 
于 2014-01-21T21:56:58.197 回答