使用Teradata数据库,可以通过Java将NaN,-Inf和+ Inf的值加载到FLOAT列中。不幸的是,一旦这些值进入表中,当编写需要过滤掉它们的SQL时,它们会使生活变得困难。没有IsNaN()函数,也不能“CAST('NaN'作为FLOAT)”并使用相等比较。
我想做的是,
SELECT
SUM(VAL**2)
FROM
DTM
WHERE
NOT ABS(VAL) > 1e+21 AND
NOT VAL = CAST ('NaN' AS FLOAT)
但是失败了,错误2620,“格式或数据包含一个坏字符。”,特别是在CAST上。我试过简单的“......而不是VAL ='NaN'”,由于类似的原因也失败了(3535,“字符串转换为数值失败。”)。我似乎无法弄清楚如何在SQL语句中表示NaN。即使我能在SQL语句中成功表示NaN,我也会担心比较会失败。根据IEEE 754规范,NaN = NaN应评估为假。我真正需要的是一个IsNaN()函数。然而,这个功能似乎并不存在。
答案 0 :(得分:0)
我已经找到了解决办法,我将与那些寻求解决方案的人分享。但首先,我很明显Teradata对NaN浮点值的处理是不完整的,我偶然发现的任何行为都可能是无意识的,并且在不同版本中不一致。所以我提供以下免费建议,没有任何保证,承诺或责任。注意事项。
在深入研究数据之后,我发现如果我将FLOAT值CAST到VARCHAR(50),则NaN值将以22个星号(**********************
)的字符串形式出现。我可以转换为VARCHAR(1),而NaN则作为单个星号(*
)出现。这种比较并不差。
SELECT
SUM(VAL**2)
FROM
DTM
WHERE
NOT CAST (VAL AS VARCHAR(1)) = '*' AND
ABS(VAL) < 1.0e+21
我会注意到两件事。
首先,我对我的Teradata版本的“NOT ABS(VAL)&gt; 1.0e + 21”的原始愿望似乎被转换为“ABS(VAL)&lt; = 1.0e + 21”。这(有时)失败是因为比较的等式 - 错误[2651],“操作错误计算涉及VAL的表达式”。我假设转换为“NOT&gt;” “&lt; =”正在发生,因为“NOT ABS(VAL)&gt; = 1.0e + 21”工作正常(但看起来很难看)。使用“ABS(VAL)&lt; 1.0e + 21”可以正常工作并捕捉到需求。
其次,虽然我无法一致地重现它,但我的历史中有一些例子,其中“ABS(VAL)&lt; = 1.0e + 21”确实有效地筛选出NaN,有些地方没有,有些地方在哪里它失败了[2651](见上文),但SQL和表中的数据是相同的。我可以得出的唯一结论是,当涉及NaN(或者它认为可能是)时,Teradata在评估比较时的方式不一致。不同的放大器可能会以不同的方式处理它,但我不确定。也就是说,where子句中的上述两个比较一致且有效地筛选出Inf和NaN值。