如何处理数据仓库中重复id包含略有不同值的维度表?

Posted

技术标签:

【中文标题】如何处理数据仓库中重复id包含略有不同值的维度表?【英文标题】:How to handle a dimension table with duplicate ids containing slightly different values in data warehouse? 【发布时间】:2018-05-17 23:39:14 【问题描述】:

我正在我的公司构建数据仓库,我遇到了这样一种情况,即我正在提取名称略有不同但绑定到同一个 ID 的数据。这显然是个问题,因为我的维度表每个 ID 应该只有一条记录

例如:

+======+===================+
|  id  |      name         |
+======+===================+
|  185 | AAAA              |
+------+-------------------+
|  185 | AAAB              |
+------+-------------------+
|  197 | XXXA              |
+------+-------------------+
|  197 | XXXB              |
+------+-------------------+
|  197 | XXXC              |
+------+-------------------+

如您所见,ID 字段应该与一个唯一值相关联,但有些字符串会有细微的变化,但与同一个 ID 相关联。一种想法是规范化字符串,但我们会丢失一些元数据。此外,我应该注意到我们正在使用 Redshift,这就是没有强制执行唯一 id 约束的原因。这个问题的最佳解决方案是什么?

【问题讨论】:

每个 unique_Id 可能有多少这样的名称变体?还需要查询姓名吗? 名称会随着时间而改变吗?你对旧名字感兴趣吗?这是数据质量问题吗? 每个 ID 最多有 5 个变体,这只是 ID 总数的 10% 左右的问题。我没有预见到我们实际上需要查询名称的情况。 问题是我们从中拉出的这个营销平台。它不是一个理想的工作平台,这只是它的众多缺点之一。有几个分支机构运行相同的活动,他们将一些元数据附加到整体活动名称,这是我们获得这些变化的地方,所以这些额外的元数据并不是很重要,但如果找到一个允许我们保留的解决方案会很好它。 【参考方案1】:

在维度表中保留最新的名称,并为“历史”创建一个辅助表,以防您将来需要其他名称。 我在用户维度上遇到了类似的情况,并按照我描述的方式实现了它。您可以选择一个规则来决定哪一个将出现在维度表中

在您的示例中,这两个表将如下所示

dim table
+======+===================+
|  id  |      name         |
+======+===================+
|  185 | AAAB              |
+------+-------------------+
|  197 | XXXC              |
+------+-------------------+

dim_hist table

+======+========+=================+
|  id  | dim_id |    name         |
+======+======+===================+
|  101 | 185  | AAAA              |
+------+------+-------------------+
|  102 | 197  | XXXA              |
+------+------+-------------------+
|  103 | 197  | XXXB              |
+------+------+-------------------+

使用昏暗表中的 id,您可以连接两个表并访问其他名称

【讨论】:

我已经想出了一个令人满意的方法,但这是对该方法的一个很好的扩展。 好奇,你是怎么处理的 我刚刚发布了我的解决方案作为答案。【参考方案2】:

我不知道这是否是最佳解决方案,但它是我们为我们的情况选择接受的解决方案。本质上,我在维度表上执行自连接并添加一个列,该列选择每个 ID 的最短字符串。由于通常每个值之间的差异是由于附加到基本字符串的数据造成的,因此最短的字符串应该返回基本字符串,这是我们正在寻找的字段中最重要的部分。

这是我为执行此操作而编写的 sql 代码:

create table tmp_dim_offers as (
  -- create subquery
  with normalized_dim_offers as (
      select
        t1.id_offer,
        t1.dim_offer_name,
        min(t2.dim_offer_name) as normalized_offer_name
      from dim_offers as t1
        join dim_offers as t2 on t1.id_offer = t2.id_offer
      group by 1, 2
      order by t1.id_offer
  )
  -- select distinct ids and normalized offer name
  select distinct
    normalized_dim_offers.id_offer              as id_offer,
    normalized_dim_offers.normalized_offer_name as dim_offer_name
  from normalized_dim_offers
  order by normalized_dim_offers.id_offer
);

-- drop existing dim_offers table and replace with new normalized table
begin;
alter table dim_offers rename to dim_offers_to_delete;
alter table tmp_dim_offers rename to dim_offers;
drop table dim_offers_to_delete cascade;
commit;

【讨论】:

一个小建议。始终使用列名,而不是 ORDER BY、GROUP BY 等的序号。【参考方案3】:

如何在维度表中添加一个新列并用 UUID 值填充它? UUID 列充当主键。

此外,这也是我跟踪历史数据的方式。我认为您的问题是有人随着时间的推移修改了源表中的记录。通过使用 UUID 作为 pkey,我们不需要覆盖记录,因此我们可以保持版本控制。

【讨论】:

以上是关于如何处理数据仓库中重复id包含略有不同值的维度表?的主要内容,如果未能解决你的问题,请参考以下文章

如何处理数据仓库设计中同样增长的事实/维度表?

如何处理具有相似属性的维度?

SQL - 加载没有业务ID的数据仓库维度表?

大数据学习(三十一)数据仓库如何处理缓慢变化维

如何处理数据仓库中用户可以更改的代码表属性

关于数据仓库的基本问题