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;

1 つのレコードを次のレコードと比較して、最初のレコードの終了日と 2 番目のレコードの開始日の間に 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;

クエリを実行すると、2012 年 7 月 1 日から 2012 年 11 月 1 日までの雇用ギャップが誤って計算されます。これは、そのレコードの開始日と終了日が前のレコードの間で始まるため、正しくありません。クエリは、ギャップに対して次の結果セットを生成する必要があります。

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 以降に最適なソリューションです。Ask tom https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:529176000346581356のA Boucherへのすべてのクレジット

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

たぶん古い投稿...しかし、ここに答えがあります:

まず、範囲が重複する可能性を排除し、重複しない範囲リストで結果を表現する必要があります。これは簡単な作業ではありません。次のクエリを使用して実行できます。

    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 に答える