如何处理数据仓库中重复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包含略有不同值的维度表?的主要内容,如果未能解决你的问题,请参考以下文章