我正在Hue中运行一个hive表的sum函数,并获得NaN的返回值。
这是我的代码:
select sum(v1) from hivedb.tb1;
我不知道为什么它会给我一个NaN的结果。我检查了我的任何v1值是否为空:
select * from hivedb.tb1 where v1 is null;
,事实证明没有记录具有空值。该表有1亿行,所以我无法对每条记录进行手动检查。
感谢任何帮助。提前谢谢!
更新1 我手动筛选了前1000行,幸运地在tb1中发现了一些NaN的异常值。它是由前面步骤中的一些舍入误差引起的。所以我的问题1可能已经回答了。如果您认为可能有其他原因,请随时对其发表评论。
我仍然不知道如何使用有效的方法来查找具有NaN值的行。所以我仍然期待着我的问题#2的任何答案。请随意分享。感谢您的帮助。
更新2 在讨论部分的下面接受的答案的帮助下解决了这个问题。有多种方法可以解决它。
答案 0 :(得分:4)
Hive依赖于Java (加上Null和朋友的SQL特定语义),而Java则遵循IEEE标准的数字语义。这意味着...... NaN很棘手。
引用that post ...
(Float.NaN == Float.NaN)
总是返回false。实际上,如果你 看看Float.isNaN()
的JDK实现,一个数字是 如果它不等于它自己(这是有意义的,因为 一个数字应该等于它自己)。
这同样适用于Double.NaN
因此,向您展示如何使用名为reflect2
的(未记录的)Hive函数没有意义,它允许您在Hive列上调用原始Java方法,即
where v1 is not null and not reflect2(v1, "isNaN")
...因为 - 理论上 - 你可以简单地陈述:
where v1 is not null and v1=v1
免责声明 - 我见过Hive优化器进行积极优化的情况"并且产生错误的结果。
换句话说,如果简单的v1=v1
子句没有按预期过滤出NaN值,那么请查看reflect2
...
编辑 - 实际上,优化器似乎忽略了某些版本的Hive 中的v1=v1
子句(请参阅注释)所以有必要制定一个更加狡猾的公式:
v1 +1.0 > v1
应该有效...除非舍入错误导致abs(v1)
<< 1或abs(v1)
>> 1 v1 =0.0
最后,最强大的方法似乎尝试 cast(v1 as String) <>'NaN'
(因为所有可能的NaN值都显示为&#34; NaN&#34;即使它们是并非严格意义上的#34;在算术意义上相等&#34; 。
<小时/> 关于
reflect2
的附注 - 您可以看到the official Hive doc确实没有提到它,而reflect
被提及(甚至有specific Wiki entry)。但它早在Hive V0.11 cf. Hive-4025
编辑 - Java&#34;反思&#34;现在默认情况下已禁用ODBC / JDBC / Hue连接 (请参阅注释) ,并且在使用安全插件(如ranger或Sentry)时无法重新启用。因此它的用法仅限于(已弃用的)hive
CLI。
答案 1 :(得分:1)
您可以将NaN视为
SELECT SUM(CAST(IF(v1 ='NaN', 0, v1)) as Double) FROM hivedb.tb1
答案 2 :(得分:0)
不确定这是否适用于许多情况,但在 Hive 3 中我得到了:
select float('NaN') = float('NaN')
返回真
理论上如此:
select * from hivedb.tb1 where v1 <> float('NaN');
应该做到这一点