为什么在事实表中将NULL值映射为0?

7

在维度建模的数据仓库中,为什么事实表中的度量字段通常将NULL值映射为0?


这是因为在数据分析中,NULL值可能会导致不准确的结果。如果在计算时出现NULL值,它们将被忽略并且无法进行计算。为了避免这种情况,通常将NULL值映射为0,以确保计算的准确性和一致性。
4个回答

17

虽然你已经接受了另一个答案,但我认为使用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()也适用相同的推理。
第二个问题是,如果0是默认值,那么你如何区分0是默认值还是真实值?例如,“以欧元计算的运费”这一度量标准中,NULL表示客户自己取货,因此没有运费,而零表示订单免费发货给客户。你不能用零来替换NULL,否则将完全改变数据的含义。当然,你可以从其他维度(例如,运输方式)中清楚地辨别两者之间的区别,但这会增加报告的复杂性和理解数据的难度。

5

这要看你所建模的内容,但通常是为了避免聚合操作时出现复杂情况。在许多场景中,将 NULL 视为 0 是有意义的。

例如,某个时间段内有 NULL 订单的客户,或者销售人员的销售收入为 NULL(真是太丢脸了!)。


感谢您的回答。我认为用零替换会影响一些计算(例如COUNT)? - jrara
COUNT 处理 NULL 的方式不同,因此仍然有意义。您可以明确计算关系中的 NULL 值数量。您无法真正将值 5 + 3 + 20 + NULL + 8 相加(即 SUM)。 - Yuck
@Yuck,Aggregate SUM(measure_here) 忽略空条目。 - Damir Sudarevic
2
正如Pondlife所解释的那样,用零替换NULL将破坏平均值,这是这个答案的问题。 - Mike McAllister

1
主要原因是数据库对空值空白的处理方式不同,尽管它们在人眼中看起来像是空白或零。
这里有一个链接,链接到Ralph Kimball关于同一主题的旧设计提示。 这篇博客文章讨论了避免度量中出现空值的方法,并提供了一些建议。

0

如果您打算在事实列上进行平均值计算,则应使用 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使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接