空值处理
什么是空值?
以下几种可能都会被理解为空值:
null:用于表示数据项不包含有效数据,缺少数据或数据是未知的。可以存在于所有类型数据里。在不同类型数据库数据表里,可能显示为空白,或者显示为 null。
空字符串:空文本字符串,仅存在文本类型里,因为不可见,可能和 null 混淆。
文本 null:实际上是文本的 'null', 包含大小写和混写格式。部分场景里,用户可能出于和有值的数据区分开的目的,在数据落库时,把文本字段里的空值替换为文本字符串 'null'。
空值的影响
任何表达式或者函数公式里,任意部分值为 null 时,最终结果通常返回 null 值。例如
CONCAT([字段A], [字段B])
,某一行数据中有 null 值,则该行结果返回 null;条件判断出现 null=null,返回null而不是true。使用
COUNT([字段]) /
计数统计会过滤掉 null 值,但是不会过滤掉空字符串;COUNT(DISTINCT[字段])
计算结果比实际结果少1。COUNT(DISTINCT[字段])
ETL里列转行的时候,要转换的字段为 null 值的话,所在数据行会整个被过滤掉,导致数据丢失。
字段类型和值内容不符合时,数据显示为 null,会误导用户认为无数据。
数据集设置去重主键,增量更新的时候,数据中还是有重复的数据,因为无法对主键里的null去重。
空值判断和处理方式
数据集
概览页面 -- 筛选数据 -- 选择字段,类型“选择”。null值显示为 (null),空字符串显示为空白,其他文本类型 null 则作为文本显示。如果要设置去重主键,则需要保证用作去重主键的字段不能包含null值。数据集中无法对字段中的空值直接替换和处理,建议在ETL里操作,或者新建计算字段用函数处理。
ETL
数据探查(4.9及以后版本):在需要的节点后面增加“数据探查”节点,选择字段,查看该字段的 null 值和枚举值概况。
Null值替换:把 null 值替换为其他值;值替换:可以替换空字符串(或null)为其他值。替换目标值必须和字段本身类型保持一致。
3. 针对需要根据一定逻辑判断并替换空值的情况,可以添加计算字段,使用Spark SQL函数进行处理。常用的空值处理函数如下:
用途 | 函数 | 举例 | 结果 |
判断是否为 null 值 | isnull([expr]); [expr] is null | true/false | |
判断是否非 null 值 | isnotnull([expr]); [expr] is not null | true/false | |
把 expr1 里的 null 值替换为 expr2 | ifnull([expr1], [expr2]) | ifnull(null,0) | 0 |
nvl([expr1], [expr2]) | nvl(null,0) | 0 | |
如果 expr1 不为 null 则返回 expr2,否则返回 expr3 | nvl2([expr1], [expr2], [expr3]) | nvl2(NULL, 2, 1) | 1 |
返回第一个非 null 值的值 | coalesce([expr1], [expr2], ...) | coalesce(NULL, 1, NULL) | 1 |
如果2个 expr 相同则返回 null,否则返回 expr1 | nullif([expr1], [expr2]) | nullif(2, 2) | null |
判断是否为空字符串 | [expr]='' [expr] <>'' | true/false | |
判断两个值是否相等,两者都为null需返回true,有一个null返回false | [expr1] <=> [expr2] | true <=> NULL | false |
卡片
如果不希望计算结果为 null 的地方展示为空,则可以在卡片右侧样式栏「特殊值」里把 null 值显示为其他数值或文本。
注意:特殊值设置仅修改展示效果,并不能把 null 值真正替换为其他数据并参与计算。例如,对存在 null 的数值字段排序,null 值只能排在最前或者最后,不会因为设置了把 null 显示为0,就把对应的数据排在正数和负数中间。
如果 null 值需要参与计算,则建议在ETL里处理完毕,或者在卡片里新建计算字段,非直连数据集用以上列表里的 Spark 函数处理后再使用新的字段参与计算,直连数据集需要用数据库对应的函数。
案例
字段显示为null,但是判断并替换null值为什么不生效?
「空日期替换」公式: ifnull([日期2],date('2099-01-01'))
原因分析:公式用法本身是没有问题的。检查字段「日期2」,发现是新建的计算字段,字段没有使用函数,直接引用另一个字段「日期1」,然后格式设置为“日期”,如下图。而「日期1」是个数字组成的日期,类型为String。
用户本意是要把文本类型日期转换为标准日期格式,然后替换 null 值。但是不同类型字段必须要使用 SQL 函数进行转换才能生效,仅在新建字段里修改字段类型不会真正生效。 真实类型和展示类型冲突时,系统默认显示null 值,但是实际上是有值的,此时用函数 isnull([日期2])
验证结果也是非 null 值 (false) 。
解决办法:修改「日期2」公式为 to_date([日期1],'yyyyMMdd')
。验证结果如下图。