如何在Hive中过滤出具有NaN值的行?

时间:2017-04-20 17:33:08

标签: sql hadoop hive nan hue

我正在Hue中运行一个hive表的sum函数,并获得NaN的返回值。

这是我的代码:

select sum(v1) from hivedb.tb1;

我不知道为什么它会给我一个NaN的结果。我检查了我的任何v1值是否为空:

select * from hivedb.tb1 where v1 is null;

,事实证明没有记录具有空值。该表有1亿行,所以我无法对每条记录进行手动检查。

  1. 有人知道我为什么会得到NaN的结果吗?
  2. 如果是因为我在某些行中有一些异常值,我怎么才能找到它们?
  3. 感谢任何帮助。提前谢谢!

    更新1 我手动筛选了前1000行,幸运地在tb1中发现了一些NaN的异常值。它是由前面步骤中的一些舍入误差引起的。所以我的问题1可能已经回答了。如果您认为可能有其他原因,请随时对其发表评论。

    我仍然不知道如何使用有效的方法来查找具有NaN值的行。所以我仍然期待着我的问题#2的任何答案。请随意分享。感谢您的帮助。

    更新2 在讨论部分的下面接受的答案的帮助下解决了这个问题。有多种方法可以解决它。

    1. 使用条件选择v1 + 1> v1。它将选择具有非NaN值的行。
    2. 使用强制转换的条件选择(v1 as String)=' NaN'。它将选择具有NaN值的行。

3 个答案:

答案 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');

应该做到这一点