this algorithmの適応では、我々はすでに重複を扱うことができます。質問に与えられたわずか2つのPerson
テーブルと
declare @PersonA table(ClientID int, ID int, [From] date, Till date);
insert into @PersonA values (1,10,'20170101','20170430'),(1,12,'20170801','20180112');
declare @PersonB table(ClientID int, ID int, [From] date, Till date);
insert into @PersonB values (1,6,'20170301','20170630');
declare @PersonC table(ClientID int, ID int, [From] date, Till date);
insert into @PersonC values (1,12,'20170401','20170625');
declare @PersonD table(ClientID int, ID int, [From] date, Till date);
insert into @PersonD values (1,14,'20170501','20170525'),(1,14,'20170510','20171122');
with X(ClientID,EdgeDate)
as (select ClientID
,case
when toggle = 1
then Till
else [From]
end as EdgeDate
from
(
select ClientID,[From],Till from @PersonA
union all
select ClientID,[From],Till from @PersonB
union all
select ClientID,[From],Till from @PersonC
union all
select ClientID,[From],Till from @PersonD
) as concated
cross join
(
select-1 as toggle
union all
select 1 as toggle
) as toggler
),merged
as (select distinct
S.ClientID
,S.EdgeDate as [From]
,min(E.EdgeDate) as Till
from
X as S
inner join X as E
on S.ClientID = E.ClientID
and S.EdgeDate < E.EdgeDate
group by S.ClientID
,S.EdgeDate
),prds
as (select distinct
merged.ClientID
,merged.[From]
,merged.Till
,A.ID as PersonA
,B.ID as PersonB
,C.ID as PersonC
,D.ID as PersonD
from
merged
left join @PersonA as A
on merged.ClientID = A.ClientID
and A.[From] <= merged.[From]
and merged.Till <= A.Till
left join @PersonB as B
on merged.ClientID = B.ClientID
and B.[From] <= merged.[From]
and merged.Till <= B.Till
left join @PersonC as C
on merged.ClientID = C.ClientID
and C.[From] <= merged.[From]
and merged.Till <= C.Till
left join @PersonD as D
on merged.ClientID = D.ClientID
and D.[From] <= merged.[From]
and merged.Till <= D.Till
where not(A.ID is null
and B.ID is null
and C.ID is null
and D.ID is null
)
)
select ClientID
,[From]
,case
when Till = lead([From]
) over(order by Till)
then dateadd(d,-1,Till)
else Till
end as Till
,PersonA
,PersonB
,PersonC
,PersonD
from
prds
order by ClientID
,[From]
,Till;
出力:スクリプトの
+----------+------------+------------+---------+---------+
| ClientID | From | Till | PersonA | PersonB |
+----------+------------+------------+---------+---------+
| 1 | 2017-01-01 | 2017-02-28 | 10 | NULL |
| 1 | 2017-03-01 | 2017-04-29 | 10 | 6 |
| 1 | 2017-04-30 | 2017-06-30 | NULL | 6 |
| 1 | 2017-08-01 | 2018-01-12 | 12 | NULL |
+----------+------------+------------+---------+---------+
出力、それは上記のようです
+----------+------------+------------+---------+---------+---------+---------+
| ClientID | From | Till | PersonA | PersonB | PersonC | PersonD |
+----------+------------+------------+---------+---------+---------+---------+
| 1 | 2017-01-01 | 2017-02-28 | 10 | NULL | NULL | NULL |
| 1 | 2017-03-01 | 2017-03-31 | 10 | 6 | NULL | NULL |
| 1 | 2017-04-01 | 2017-04-29 | 10 | 6 | 12 | NULL |
| 1 | 2017-04-30 | 2017-04-30 | NULL | 6 | 12 | NULL |
| 1 | 2017-05-01 | 2017-05-09 | NULL | 6 | 12 | 14 |
| 1 | 2017-05-10 | 2017-05-24 | NULL | 6 | 12 | 14 |
| 1 | 2017-05-25 | 2017-06-24 | NULL | 6 | 12 | 14 |
| 1 | 2017-06-25 | 2017-06-29 | NULL | 6 | NULL | 14 |
| 1 | 2017-06-30 | 2017-07-31 | NULL | NULL | NULL | 14 |
| 1 | 2017-08-01 | 2017-11-21 | 12 | NULL | NULL | 14 |
| 1 | 2017-11-22 | 2018-01-12 | 12 | NULL | NULL | NULL |
+----------+------------+------------+---------+---------+---------+---------+
テーブルと4つの
Person
テーブルがあります。これを行う目的は?追加値の列を追加することは、一般に、セットベースのクエリの原則に反するため、SQLの習慣としては貧弱です。あなたが割り当てられた月と人のリストが必要な場合は、プレゼンテーション層でフォーマットされた通常のデータセットを使用する方がよいでしょう。 – iamdave@iamdave - これはちょうど私が与えられた仕事です。私はそれも好きではありませんし、私は別のアプローチを見つけることを試みるでしょうが、今私はこれに固執しています – quin61
再び、どのような目的のために?データはどこで使用されるのでしょうか?分析のために優れている場合は、標準データセットをピボットすることができます。 SSRSのようなレポートレイヤーを使用している場合は、そこでピボットすることができます。私はあなたがこのフォーマットのデータを他の用途のためのクエリから直接求められていると信じることを拒否しますか? – iamdave