2017-02-01 39 views
2

我有2個表(實際上有4個,但現在可以說是2),這樣的數據:有效時間 - SQL VIEW

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)。
所以在最後的觀點中,一個客戶不能有任何重疊的日期。

我不知道如何解決這個問題。

+0

什麼是這樣做的目的?添加列的額外值通常是很差的SQL實踐,因爲它違背了基於集合的查詢原則。如果你只是想要一個月份列表和分配給你的人,使用在表示層中格式化的常規數據集會更好。 – iamdave

+0

@iamdave - 這只是我給的任務。我不喜歡它,我會嘗試找到不同的方法,但現在我堅持這個 – quin61

+0

再次,爲了什麼目的?數據最終將被用於何處?如果它進入excel分析,你可以在那裏轉換一個標準數據集。如果您有像SSRS這樣的報告圖層,您可以在此處進行轉換。我拒絕相信你被詢問這種格式的數據直接從查詢中找不到其他用途? – iamdave

回答

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

我從此查詢中得到的輸出與問題中的輸出不匹配。您沒有爲每個新人組合顯示一個行/期間。 – iamdave

+0

謝謝。 OP樣本數據中的日期並不一致,但我明白了......讓我們試着解決。 – dlatikay

+2

他們對我有意義,意思是重疊。輸出結果必須是每個不同人員組合開始和結束日期的行,以及組合開始和結束的日期以及包含哪些人員。 – iamdave