1

私はSQLに慣れていないので、私はこれからできることを学びたいと思っています。おかげSQL Server 2014オーバーラップする日付範囲をマージする

私はこのように見ているのSQL Server 2014データベース内200.000行を持つテーブルがあります:あなたはそこに各契約のために複数のオーバーラップすることができ、私は希望持って見ることができるように

CREATE TABLE DateRanges 
(
    Contract VARCHAR(8), 
    Sector VARCHAR(8), 
    StartDate DATE, 
    EndDate DATE 
); 

INSERT INTO DateRanges (Contract, Sector, StartDate, Enddate) 
    SELECT '111', '999', '01-01-2014', '03-31-2014' 
    union 
    SELECT '111', '999', '04-01-2014', '06-30-2014' 
    union 
    SELECT '111', '999', '07-01-2014', '09-30-2014' 
    union 
    SELECT '111', '999', '10-01-2014', '12-31-2014' 
    union 
    SELECT '111', '888', '08-01-2014', '08-31-2014' 
    union 
    SELECT '111', '777', '08-15-2014', '08-31-2014' 
    union 
    SELECT '222', '999', '01-01-2014', '03-31-2014' 
    union 
    SELECT '222', '999', '04-01-2014', '06-30-2014' 
    union 
    SELECT '222', '999', '07-01-2014', '09-30-2014' 
    union 
    SELECT '222', '999', '10-01-2014', '12-31-2014' 
    union 
    SELECT '222', '666', '11-01-2014', '11-30-2014' 
    UNION 
    SELECT '222', '555', '11-15-2014', '11-30-2014'; 

です私はこれを行うことができると私は、このサイトで見てきた例は非常に私の問題に適合しない方法を見つけ出すことはできません。この

Contract Sector StartDate  EndDate 
    --------------------------------------------- 
    111  999  01-01-2014 07-31-2014 
    111  888  08-01-2014 08-14-2014 
    111  777  08-15-2014 08-31-2014 
    111  999  09-01-2014 12-31-2014 

    222  999  01-01-2014 10-31-2014 
    222  666  11-01-2014 11-14-2014 
    222  555  11-15-2014 11-30-2014 
    222  999  12-01-2014 12-31-2014 

ようになります。

は、この答えは、いくつかの異なる技術を利用し、あなたの種類の助けと支援

+0

終了日'07 -31-2014' どのように計算されますか?あなたのデータにはありません。 –

+0

その日付はデータにありません。別のセクターの新しい日付範囲が始まる前の最後の日付として計算されます –

+0

同様の質問が以前に何度も尋ねられ、何度も回答されています。 https://stackoverflow.com/questions/2561130/merge-overlapping-date-intervals解決方法の詳細については、この記事をお試しください:https://www.experts-exchange.com/articles/ 3952/ranges-gap-overlaps-for-number-and-date-ranges.html – Alex

答えて

0

いただきありがとうございます。最初はで、関連するすべてのテーブルを作成します。は、と一意のContractの値を得て、両方の値のすべての組み合わせを取得します。 2番目の数字はlagrow_numberのようなで、以下のコメントに詳述されているさまざまなものを決定します。最後に、おそらく最も重要なことに、が、Contract/Sectorの組み合わせが終了し、次が始まるときを決定する。

回答:

--determine range of dates 
declare @bgn_dt date = (select min(StartDate) from DateRanges) 
    , @end_dt date = (select max(EndDate) from DateRanges) 

--use a recursive CTE to create a record for each day/Contract 
; with dates as 
    (
     select @bgn_dt as cal_date 
     union all 
     select dateadd(d, 1, a.cal_date) as cal_date 
     from dates as a 
     where a.cal_date < @end_dt 
    ) 
select d.cal_date 
, c.Contract 
into #contract_dates 
from dates as d 
cross apply (select distinct Contract from DateRanges) as c 
option (maxrecursion 0) 

--Final Select 
select f.Contract 
, f.Sector 
, min(f.cal_date) as StartDate 
, max(f.cal_date) as EndDate 
from (
    --Use the sum-over to obtain the Island Numbers 
    select dr.Contract 
    , dr.Sector 
    , dr.cal_date 
    , sum(dr.IslandBegin) over (partition by dr.Contract order by dr.cal_date asc) as IslandNbr 
    from (
     --Determine if the record is the start of a new Island 
     select a.Contract 
     , a.Sector 
     , a.cal_date 
     , case when lag(a.Sector, 1, NULL) over (partition by a.Contract order by a.cal_date asc) = a.Sector then 0 else 1 end as IslandBegin 
     from (
      --Determine which Contract/Date combinations are valid, and rank the Sectors that are in effect 
      select cd.cal_date 
      , dr.Contract 
      , dr.Sector 
      , dr.EndDate 
      , row_number() over (partition by dr.Contract, cd.cal_date order by dr.StartDate desc) as ConractSectorRnk 
      from #contract_dates as cd 
      left join DateRanges as dr on cd.Contract = dr.Contract 
             and cd.cal_date between dr.StartDate and dr.EndDate 
      ) as a 
     where a.ConractSectorRnk = 1 
     and a.Contract is not null 
     ) as dr 
    ) as f 
group by f.Contract 
, f.Sector 
, f.IslandNbr 
order by f.Contract asc 
, min(f.cal_date) asc 

出力:

+----------+--------+------------+------------+ 
| Contract | Sector | StartDate | EndDate | 
+----------+--------+------------+------------+ 
|  111 | 999 | 2014-01-01 | 2014-07-31 | 
|  111 | 888 | 2014-08-01 | 2014-08-14 | 
|  111 | 777 | 2014-08-15 | 2014-08-31 | 
|  111 | 999 | 2014-09-01 | 2014-12-31 | 
|  222 | 999 | 2014-01-01 | 2014-10-31 | 
|  222 | 666 | 2014-11-01 | 2014-11-14 | 
|  222 | 555 | 2014-11-15 | 2014-11-30 | 
|  222 | 999 | 2014-12-01 | 2014-12-31 | 
+----------+--------+------------+------------+ 
+0

ありがとうございました.....それは素晴らしいです –

+0

私の質問に答えるためにあなたの偉大な仕事とトラブルをありがとう –

関連する問題