【问题标题】:Why NULL values are mapped as 0 in Fact tables?为什么 NULL 值在 Fact 表中映射为 0?
【发布时间】:2012-01-08 05:07:48
【问题描述】:

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

【问题讨论】:

    标签: sql-server ssis null data-warehouse dimensional-modeling


    【解决方案1】:

    这取决于您要建模的内容,但通常是为了避免执行聚合时出现复杂情况。在许多情况下,出于这些目的将NULL 视为0 是有意义的。

    例如,在给定时间段内拥有NULL 订单的客户。或者是销售收入为NULL 的销售人员(真丢脸!)。

    【讨论】:

    • 感谢您的回答。我在想替换零会扭曲一些计算(例如 COUNT)?
    • COUNT 处理 NULL 的方式不同,所以它仍然有意义。您可以显式计算关系中NULL 值的数量。你不能真正加起来(即SUM)值5 + 3 + 20 + NULL + 8
    • @Yuck,聚合 SUM(measure_here) 忽略空条目。
    • 这个答案的问题,正如 Pondlife 所解释的那样,用零替换 NULL 会破坏平均值。
    【解决方案2】:

    虽然您已经接受了另一个答案,但我想说使用 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 表示客户自己取货,因此没有运费,而零表示订单是免费运送给客户的。在不完全改变数据含义的情况下,您不能使用零来替换 NULL。您显然可以争辩说,应该从其他维度(例如运输方式)明确区分,但这会增加报告和理解数据的复杂性。

    【讨论】:

      【解决方案3】:

      主要原因是数据库处理 nullsblankszeros 不同,即使它们在人类看来就像空白或零眼睛。

      这是link 对同一主题的Ralph Kimball 的旧设计提示的@。

      This blogpost 谈到了如何在度量中避免空值并给出了一些建议。

      【讨论】:

        【解决方案4】:

        如果您打算对事实列进行平均,则应使用 NULL 而不是 0。这是我唯一一次相信 NULLS 在 dwh 事实或维度上是可以接受的

        如果事实值未知/迟到,则最好保留为 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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-12-29
          • 1970-01-01
          • 2013-07-04
          • 1970-01-01
          • 1970-01-01
          • 2020-07-07
          • 1970-01-01
          相关资源
          最近更新 更多