在维度建模的数据仓库中,为什么事实表中的度量字段通常将NULL值映射为0?
这是因为在数据分析中,NULL值可能会导致不准确的结果。如果在计算时出现NULL值,它们将被忽略并且无法进行计算。为了避免这种情况,通常将NULL值映射为0,以确保计算的准确性和一致性。
在维度建模的数据仓库中,为什么事实表中的度量字段通常将NULL值映射为0?
虽然你已经接受了另一个答案,但我认为使用NULL实际上是更好的选择,原因有几个。
第一个原因是当存在NULL时,聚合函数返回“正确”的答案(即用户倾向于期望的答案),而当你使用零时,它们会给出“错误”的答案。考虑在这两个查询中AVG()函数的结果:
-- with zero; gives 1.5
select SUM(measure), AVG(measure)
from
(
select 1.0 as 'measure'
union all
select 2.0
union all
select 3.0
union all
select 0
) dt
-- with null; gives 2
select SUM(measure), AVG(measure)
from
(
select 1.0 as 'measure'
union all
select 2.0
union all
select 3.0
union all
select null
) dt
如果我们假设这里的度量标准是“生产物品所需的天数”,而NULL表示仍在生产中的物品,那么零会得到错误的答案。对于MIN()和MAX()也适用相同的推理。这要看你所建模的内容,但通常是为了避免聚合操作时出现复杂情况。在许多场景中,将 NULL
视为 0
是有意义的。
例如,某个时间段内有 NULL
订单的客户,或者销售人员的销售收入为 NULL
(真是太丢脸了!)。
如果您打算在事实列上进行平均值计算,则应使用 NULL 而不是 0。我认为这是唯一一种情况,在数据仓库事实或维度中使用 NULL 是可以接受的。
如果事实值未知/延迟到达,则保留为 NULL 最佳。
聚合函数(如 MIN、MAX)会简单地忽略 NULLS。
(记录一下,Ralph Kimball 的其中一位助手在他的课程中说过这话)
with goodf as
(
select 1 x
union all
select null
union all
select 4
)
select sum(x) sumx,min(x) minx,max(x) maxx,avg(cast(x as float)) avgx
from goodf
with badf as
(
select 1 x
union all
select 0 /* unknown */
union all
select 4
)
select sum(x) sumx,min(x) minx,max(x) maxx,avg(cast(x as float)) avgx
from badf
在badf中,高于平均水平的结果不正确,因为它将未知值的零直接作为0使用。
COUNT
处理NULL
的方式不同,因此仍然有意义。您可以明确计算关系中的NULL
值数量。您无法真正将值5 + 3 + 20 + NULL + 8
相加(即SUM
)。 - Yuck