簡體   English   中英

在 SCD2 表中合並跨時間跨度的行

[英]Merge lines over timespan in SCD2 table

我的下表來自 SCD2 表。 從這個源表中,我只選擇了幾列,這導致幾行看起來完全相似。 我想刪除不必要的行,那些包含相同數據的行,並讓 ValidFrom 列顯示第一個值,而 ValidTo 列顯示“時間跨度組”中的最后一個值。

源數據:

| Item     | Color      | ValidFrom     | ValidTo    |
| -------- | ---------- | ------------- | ---------- |
| Ball     | Red        | 2020-01-01    | 2020-03-24 |
| Ball     | Blue       | 2020-03-25    | 2020-04-12 |
| Ball     | Blue       | 2020-04-13    | 2020-05-07 |
| Ball     | Blue       | 2020-05-08    | 2020-11-14 |
| Ball     | Red        | 2020-11-15    | 9999-12-31 |
| Doll     | Yellow     | 2020-01-01    | 2020-03-24 |
| Doll     | Green      | 2020-03-25    | 2020-04-12 |
| Doll     | Green      | 2020-04-13    | 2020-05-07 |
| Doll     | Green      | 2020-05-08    | 2020-11-14 |
| Doll     | Pink       | 2020-11-15    | 9999-12-31 | 

我想要完成的是:

| Item     | Color      | ValidFrom     | ValidTo    |
| -------- | ---------- | ------------- | ---------- |
| Ball     | Red        | 2020-01-01    | 2020-03-24 |
| Ball     | Blue       | 2020-03-25    | 2020-11-14 |
| Ball     | Red        | 2020-11-15    | 9999-12-31 |
| Doll     | Yellow     | 2020-01-01    | 2020-03-24 |
| Doll     | Green      | 2020-03-25    | 2020-11-14 |
| Doll     | Pink       | 2020-11-15    | 9999-12-31 | 

請注意,項目球最初的顏色是紅色,然后是藍色,然后又變回紅色。 根據我所學到的,這使事情變得更加復雜。

謝謝你的幫助。

這是孤島和差距問題。

您可以使用解析 function 如下:

Select item, color,
       min(validfrom) as validfrom,
       Max(validto) as validto
  From
(Select t.*,
       Sum(case when lged between validfrom and validto then 0 else 1 end) 
           over (partition by item, color order by validfrom) as sm
  From
(Select t.*,
       Lag(validto) over (partition by item, color order by validfrom) as lged
  From t) t) t
Group by item, color, sm

這確實是一個間隙和島嶼問題,其中島嶼是具有相同項目和顏色的相鄰記錄。

在這里,我建議使用行號之間的差異來定義組。 這僅涉及一層嵌套,而不是使用lag()時的兩層,因此它應該是最有效的選擇:

select item, color, min(validfrom) as validfrom, max(validto) as validto
from (
    select t.*,
        row_number() over(order by validfrom) as rn1,
        row_number() over(partition by item, color order by validfrom) as rn2
    from mytable t
) t
group by item, color, rn1 - rn2

你的數據很規律。 您似乎只想組合沒有重疊或間隙的相鄰平鋪記錄。 然而,以下處理差距和更普遍的重疊:

select item, color, min(validfrom), max(validto)
from (select t.*,
             sum(case when prev_validto >= dateadd(day, -1, validfrom)
                      then 0 else 1
                 end) over (partition by item order by validfrom) as grp
      from (select t.*,
                   lag(validto) over (partition by item, color order by validfrom) as prev_validto
            from t
            ) t
     ) t
group by item, color, grp;

您正在尋找原始數據中的行島,其中“島”具有相同的項目、顏色和相鄰日期。 這通過查看相同項目和顏色的前一行來確定島嶼的開始位置。 如果沒有這樣的行或該行在當前行開始之前結束,則當前行是島的開始。

然后grp是“島嶼起點”的累積總和,可用於聚合並獲得最終結果。

您的特定數據非常有限 - 完美地平鋪了一行在下一行開始的前一天結束。 您可以使用left join做一些非常相似的事情:

select item, color, min(validfrom), max(validto)
from (select t.*,
             sum(case when tprev.color is null then 1 else 0
                 end) over (partition by t.item order by t.validfrom) as grp
      from t left join
           t tprev
           on tprev.item = t.item and
              tprev.color = t.color and
              tprev.validto = dateadd(day, -1, t.validfrom)
     ) t
group by item, color, grp
order by item, min(validfrom);

是一個說明這兩種方法的 db<>fiddle

由於行之間沒有間隙或重疊,因此此查詢就足夠了

select item, color, 
       min(validfrom) as ValidFrom,
       max(validto) as ValidTo
from tTable
group by item, color
order by item, ValidFrom;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM