有效期 - SQL VIEW

时间:2017-02-01 09:47:15

标签: tsql join view

我有2个表(实际上有4个,但现在可以说它是2个),数据如下:

Table PersonA   
ClientID    ID  From        Till
1           10  1.1.2017    30.4.2017   
1           12  1.8.2017    2.1.2018

Table PersonB       
ClientID    ID  From        Till
1           6   1.3.2017    30.6.2017

我需要生成可以显示如下内容的视图:

ClientID        From        Till        PersonA     PersonB
1               1.1.2017    28.2.2017    10         NULL
1               1.3.2017    30.4.2017    10          6
1               1.5.2017    30.6.2017   NULL         6
1               1.8.2017    02.1.2018    12         NULL

所以基本上我需要创建一个视图来显示每个客户在给定时期内的“人” 因此,当存在重叠时,客户端同时具有PersonA和PersonB(同样应该适用于PersonC和PersonD) 因此,在最终视图中,一个客户端不能有任何重叠日期。

我不知道如何处理这个问题。

1 个答案:

答案 0 :(得分:3)

this algorithm的改编中,我们已经可以处理重叠:

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;

仅使用问题中给出的两个Person表格输出:

+----------+------------+------------+---------+---------+
| 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    |
+----------+------------+------------+---------+---------+

上面的脚本输出,有四个Person表:

+----------+------------+------------+---------+---------+---------+---------+
| 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    |
+----------+------------+------------+---------+---------+---------+---------+