2013-10-14 15 views
5

最近、あるジョブの終了から開始までの30日間を超える期間がギャップとして定義されている雇用の日付間のギャップを見つけることを任されましたSQL Server - 重複する日付を含む日付の間のギャップの検出

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の経過がありますかどうかを確認するために、次のレコードに、一つのレコードの比較をやっている:次、および下記を参照、それに合わせて、クエリを思い付くことができたの最初のレコードの終了日と2番目のレコードの開始日の間の日数で、通常の場合、すなわち雇用期間が重複しない場合には問題ありません。特定の期間に複数のジョブがある場合、その特定のケースが現れました。ジョブ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日の間に雇用のギャップを計算しています。 > 2011年8月22日

03/- > 2006年8月28日

2011年6月15日 -

2003年11月7日:クエリは、ギャップのために、次の結果セットを生成する必要があります05/2013 - > 10/14/2013

私の問題は、カーソルを使わずに正しく計算する方法を考えています。私が試みてきた方法は、 EmploymentGapInfoテーブル変数に記録し、そのレコードの開始日と終了日を取得したら、テーブルを再度ループして、開始日と終了日がテーブルの他のレコードと重複していないかどうかを確認します。

カーソルを使用しようとする代わりに、セットベースのアプローチでこの問題に取り組む方法はありますか?これは、データベースで解決しようとしているのに対して、ビジネス層でそれをやり遂げることによって利益を得ることができる問題でしょうか?

ご協力いただければ幸いです。

+1

上のバウチャーへのすべてのクレジットは[SqlFiddle](HTTPを作成してみてください。デモをしてここにリンクを付ける – th1rdey3

+0

この行に'10/14/2012 - > NULL 'があるため、最後のギャップ( '03/05/2013 - > 10/14/2013')は間違っています。 –

+0

@ th1rdey3:ここにはSQL Fiddleへのリンクがあります:http://sqlfiddle.com/#!3/06753/3/0 – rc6886

答えて

0

@EmploymentGapInfoのすべての日付を昇順でソートしたテンポラリテーブルを作成することができます。その後、そのギャップを見つけることがより簡単になります。

select distinct StartDate 'GDate' 
from @EmploymentGapInfo 
union 
select distinct EndDate 
from @EmploymentGapInfo 
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日以上持つギャップを計算することができます:それは簡単な作業ではありません、あなたはこのクエリでそれをCANDOのSQL Server 2012および上記のため

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) 
4

偉大なソリューションを。 // sqlfiddle:トムを尋ねる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 
+0

私はこれが本当に古いことを知っていますが、私はちょうどあなたに感謝したいと思います!これは私が完璧にしていた非常に似た問題を解決し、私に多くの頭痛を救った。 – APH

関連する問題