1

使用 Teradata 数据库,可以通过 Java 将 NaN、-Inf 和 +Inf 的值加载到 FLOAT 列中。不幸的是,一旦这些值进入表中,在编写需要过滤掉它们的 SQL 时就会变得很困难。没有 IsNaN() 函数,您也不能“CAST ('NaN' as FLOAT)”并使用相等比较。

我想做的是,

SELECT
  SUM(VAL**2)
FROM
  DTM
WHERE
  NOT ABS(VAL) > 1e+21 AND
  NOT VAL = CAST ('NaN' AS FLOAT)

但失败并出现错误 2620,“格式或数据包含错误字符。”,特别是在 CAST 上。我尝试过简单的“... AND NOT VAL = 'NaN'”,但由于类似原因也失败了(3535,“字符串转换为数值失败。”)。我似乎无法弄清楚如何在 SQL 语句中表示 NaN。即使我可以在 SQL 语句中成功表示 NaN,我也会担心比较会失败。根据 IEEE 754 规范,NaN = NaN 应该评估为假。我真正需要的是一个 IsNaN() 函数。然而,该功能似乎并不存在。

4

1 回答 1

0

我想出了一个变通办法,我会与那些正在寻找解决方案的人分享。但首先,对我来说很明显,Teradata 对 NaN 浮点值的处理是不完整的,我偶然发现的任何行为都可能是无意的,并且在不同版本之间不一致。因此,我提供以下免费建议,不提供任何形式的保证、承诺或责任。买者自负。

在深入研究数据后,我发现如果我将 FLOAT 值转换为 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) > 1.0e+21”的渴望似乎在幕后转换为“ABS(VAL) <= 1.0e+21”。这(有时)失败,因为比较的平等药水 - 错误 [2651],“涉及 VAL 的操作错误计算表达式”。我假设正在发生从“NOT >”到“<=”的转换,因为“NOT ABS(VAL) >= 1.0e+21”工作正常(但看起来很难看)。使用“ABS(VAL) < 1.0e+21”可以很好地满足需求。

其次,虽然我无法始终如一地重现它,但在我的历史中有一些例子,其中“ABS(VAL) <= 1.0e+21”确实有效地屏蔽了 NaN,有些则没有,有些则以 [ 2651](见上文),但 SQL 和表中的数据是相同的。我能得出的唯一结论是,当涉及 NaN(或者它认为可能是)时,Teradata 在评估比较的方式上不一致。不同的放大器可能会以不同的方式处理它,但我不确定。也就是说,where 子句中的上述两个比较始终有效地筛选出 Inf 和 NaN 值。

于 2012-11-20T22:57:11.420 回答