将 EAVT table 转换为 SCD 类型 2

Converting EAVT table into SCD type 2

经过大量研究和挑选,我仍然无法找到 good/clean 将实体属性值时间戳 table 转换为 scd 类型 2 维度的解决方案。

这是问题所在: 我有一个 CRM 源,它将所有历史记录存储在 EAVT 模型中(Entity/Attribute/Value of the attribute/valid_from/valid_to)。 因此,对于每个对象(公司、产品等),我都有一个 table 和关系模型中的当前状态,以及另一个包含所有属性的所有值更改的历史记录 table valid_from/valid_to 值本身有效性的列。

我希望能够将这两个 table 合并到一个 SCD table 中,每个属性有一个 Valid_To/Valid_From 和一个列。

举个例子: 公司有两个table:

company_id name number_of_employees city
1 Company 1 500 Paris
2 Company 2 500 Paris
company_id attribute value valid_from valid_to
1 city New York 01/01/2020 01/05/2022
1 city Paris 01/05/2022 12/31/9999
1 number_of_employees 50 01/01/2021 01/01/2022
1 number_of_employees 100 01/01/2022 12/31/9999

我想要的结果如下:

company_id name city number_of_employees valid_from valid_to is_active
1 Company 1 New York null 01/01/2020 01/01/2021 false
1 Company 1 New York 50 01/01/2021 01/01/2022 false
1 Company 1 New York 100 01/01/2022 01/01/2022 false
1 Company 1 Paris 100 01/05/2022 12/31/9999 true

因此,基于此示例,我们有一家公司于 2020 年 1 月 1 日成立,纽约作为城市,当时没有员工人数。 然后我们修改了我们的公司以增加 50 作为员工人数,这发生在 01/01/2021。 我们在01/01/2022再次修改我们的公司,将员工人数更改为100,只是在01/05/2021将公司所在城市从纽约更改为巴黎

这为我们提供了公司的 4 个州,因此我们的 SCD 应包含每个州一行或 4 行。 日期应计算为重叠,valid_from 应设置为从“历史”更改的属性的 valid_to table,valid_to 应设置为valid_from 从“历史”更改的属性 table。

为了增加任务的复杂性,假设我们有大约 120 个属性,但如果一家公司从未改变(刚刚创建并且仍然具有创建时的相同状态)那么它不会存在于“当前状态” " table。因此,在我们的示例中,公司 2 根本不存在于历史 table 中,必须从第一个 table 读取到 SCD(当前 table 和历史结果 [=] 之间的联合=69=]).好玩吧! :)

为了让您了解技术环境,CRM 是 hubspot,数据从 hubspot 复制到 BigQuery,报告工具是 Power BI。

我尝试在 Power BI 和 BigQuery 中使用数据透视,这是 EAV 模型 tables 的标准解决方案,但我在计算 valid/from valid/to 在结果 SCD 中。 (此处使用旋转的示例:https://dba.stackexchange.com/questions/20275/solutions-for-reporting-off-of-an-eav-structured-database

我需要一个可以应用到多个 table 的过程(因为这个例子只针对公司,但我还有其他对象需要转换成 SCD)。 那么,在不陷入硬代码和性能问题的迷宫的情况下,将此 EAVT 数据转换为 SCD 的最佳方法是什么?以及如何动态计算valid_from/valid_to<

无论是 BigQuery 或 Power Query 还是仅仅是理论上的,任何解决方案、技巧、想法或只是简单的意见都将受到高度赞赏,因为这是我工作的公司采用整个数据文化的最后一步,并且如果我做不到,好吧……我的信誉将受到打击!所以请帮助一位迷路的 IT 专业人士! :D

太宽泛的问题 - 但无论如何,下面只是给你一个想法。显然它并没有涵盖所有情况 - 但希望你能进一步解决

select company_id, city, number_of_employees, min(day) valid_from, max(day) valid_to
from (
  select * from (
    select company_id, attribute, value, day
    from history, 
    unnest(generate_date_array(date(valid_from), if(valid_to = '9999-12-31', date('2222-12-31'), date(valid_to)))) day
  )
  pivot (any_value(value) for attribute in ('city', 'number_of_employees'))
) 
group by company_id, city, number_of_employees     

如果应用于您问题中的示例数据

with history as (
  select 1 company_id, 'city' attribute, 'New York' value,  '2020-01-01' valid_from,    '2022-01-05' valid_to union all
  select 1, 'city', 'Paris', '2022-01-05', '2222-12-31' union all
  select 1, 'number_of_employees', '50', '2021-01-01', '2022-01-01' union all
  select 1, 'number_of_employees', '100', '2022-01-01', '2222-12-31' 
)

输出是