2017-05-02 17 views
0

2017-04-01から2017-04-30までの範囲に、このテーブルのデータを入力する必要があります。私はこのような結果を取得する必要があります下の優先順位実際にSQL Server:優先順位が重複している日付の範囲を入力してください

id  startValidity endValidity priority 
------------------------------------------- 
1004 2017-04-03 2017-04-30 1 
1005 2017-04-10 2017-04-22 2 
1010 2017-04-19 2017-04-23 3 
1006 2017-04-24 2017-04-28 2 
1008 2017-04-26 2017-04-28 3 

持つもの:

id  startValidity endValidity priority 
-------------------------------------------- 
1004 2017-04-03 2017-04-09 1 
1005 2017-04-10 2017-04-18 2 
1010 2017-04-19 2017-04-23 3 
1006 2017-04-24 2017-04-25 2 
1008 2017-04-26 2017-04-28 3 
1004 2017-04-29 2017-04-30 1 
+0

あなたが達成しようとしているものについての例を挙げて、より良いあなたの質問を教えてください、差分サンプルデータでこれを試してみてください! – Tarun

+1

最初のレコードセットは、エンティティに関連するカレンダーと親エンティティのカレンダーを結合した結果です。 各レコードに有効期間があり、連続した有効期間(重複なし)のある特定の期間(つまり2017-04-01から2017-04-30まで)の有効なカレンダーをすべて取得する必要があります。ただし、 は、優先順位の高いカレンダーは優先順位の低いカレンダーよりも優先しなければなりません – Andypat

+0

出力レコードの数が入力レコードの数よりも大きくなる可能性があるため、これを単一の照会で解決することはできません。当然のことながら、それは再帰的に解決されます(「フレーミング」や「カバー」など)。個人的には、可能であれば、より高いレベルのプログラミング言語(C++、Java、C#など)で記述します。 –

答えて

1

は今エレガントなものか、より効率的な解決策を考えることはできません。 。 。

-- Sample Table 
declare @tbl table 
(
    id  int, 
    startValidity date, 
    endValidty date, 
    priority int 
) 

-- Sample Data 
insert into @tbl select 1004, '2017-04-03', '2017-04-30', 1 
insert into @tbl select 1005, '2017-04-10', '2017-04-22', 2 
insert into @tbl select 1010, '2017-04-19', '2017-04-23', 3 
insert into @tbl select 1006, '2017-04-24', '2017-04-28', 2 
insert into @tbl select 1008, '2017-04-26', '2017-04-28', 3 

-- Query 
; with 
date_range as -- find the min and max date for generating list of dates 
(
    select start_date = min(startValidity), end_date = max(endValidty) 
    from @tbl 
), 
dates as -- gen the list of dates using recursive CTE 
(
    select rn = 1, date = start_date 
    from date_range 

    union all 

    select rn = rn + 1, date = dateadd(day, 1, d.date) 
    from dates d 
    where d.date < (select end_date from date_range) 
), 
cte as -- for each date, get the ID based on priority 
(
    select *, grp = row_number() over(order by id) - rn 
    from dates d 
      outer apply 
      (
       select top 1 x.id, x.priority 
       from @tbl x 
       where x.startValidity <= d.date 
       and  x.endValidty >= d.date 
       order by x.priority desc 
      ) t 
) 
-- final result 
select id, startValidity = min(date), endValidty = max(date), priority 
from cte 
group by grp, id, priority 
order by startValidity 
+0

私は異なるデータが完全に動作するようです。 – Andypat

+0

Itzik Ben-Ganの[Packing Intervals](http://blogs.solidq.com/en/sqlserver/packing-intervals/)をご覧ください。ここに求められるのは正確ではありませんが、私はItzikのアイデアがここに適用されると思います。 –

0

私はカレンダーCTEやテーブルの目的を理解していません。 したがって、私はREcursive CTEまたはカレンダーを使用していません。

私は要件を完全に理解することはできません。

declare @tbl table 
(
    id  int, 
    startValidity date, 
    endValidty date, 
    priority int 
) 

-- Sample Data 
insert into @tbl select 1004, '2017-04-03', '2017-04-30', 1 
insert into @tbl select 1005, '2017-04-10', '2017-04-22', 2 
insert into @tbl select 1010, '2017-04-19', '2017-04-23', 3 
insert into @tbl select 1006, '2017-04-24', '2017-04-28', 2 
insert into @tbl select 1008, '2017-04-26', '2017-04-28', 3 
;With CTE as 
(
select * ,ROW_NUMBER()over(order by startValidity)rn 
from @tbl 
) 
,CTE1 as 
(
select c.id,c.startvalidity,isnull(dateadd(day,-1, c1.startvalidity) 
,c.endValidty) Endvalidity 
,c.[priority],c.rn 
from cte c 
left join cte c1 
on c.rn+1=c1.rn 
) 

select id,startvalidity,Endvalidity,priority from cte1 
union ALL 
select id,startvalidity,Endvalidity,priority from 
(
select top 1 id,ca.startvalidity,ca.Endvalidity,priority from cte1 
cross apply(
select top 1 
dateadd(day,1,endvalidity) startvalidity 
,dateadd(day,-1,dateadd(month, datediff(month,0,endvalidity)+1,0)) Endvalidity 
from cte1 
order by rn desc)CA 
order by priority 
)t4 
--order by startvalidity --if req 
関連する問題