【问题标题】:Odd Behavior on Sum (Getting Numeric Overflow)Sum 的奇怪行为(出现数值溢出)
【发布时间】:2013-07-25 20:45:24
【问题描述】:

我正在使用 SAS proc sql 查询并发现了一些奇怪的东西。首先,我尝试了这个简单的查询:

proc sql;
  CREATE TABLE test AS 
    (SELECT
       YEAR(dt) AS yr,
       MONTH(dt) AS mo,
       SUM(val) AS total
     FROM
       mydb1234.myTable
     WHERE
       myDate BETWEEN x AND y
     GROUP BY
       yr, mo);
run;

当我运行这个查询时,我收到这个错误:

ERROR: Teradata row not delivered (trget): Numeric overflow occurred during computation.

据我所知,当我的总和值太大而无法容纳proc sql 尝试使用的数据类型时,就会发生这种情况。

我决定只将要相加的数字相除:

SUM(val/1000) AS total

但是,这产生了意想不到的后果。总和小于我在 Excel 中所做的手动总和。当我向除数添加更多数量级时,总数会降低。我猜这是在消除它试图求和的较小值(例如 10/1000 与 108/10000 等),这些值永远不会达到总和,而是被读取为零。

有没有办法强制这个 proc sql 使用可以容纳我的总值的字段长度创建一个表?它们在十亿的范围内,所以我认为这没什么不寻常的。我很想知道你们的想法。

【问题讨论】:

  • 我不认为这不是 SAS 特定问题。 SAS 不会给你溢出;除非你的数字如此疯狂,以至于它不能不精确地存储在 64 位中,无论如何,情况肯定不是这样。如果您生成了超过 15 个有效数字,它可能会开始删除重要性,但它不会给您任何迹象表明它正在这样做。
  • teradata 的接口在这里如何工作?是否有 libname 到 teradata 服务器,或者它是通过,还是其他什么?
  • 有一个库,我这样引用它:FROM mydb1234.myTable 其中 mydb1234 是 libref
  • 每年总计数千亿,并没有什么特别大的。
  • 请显示使用的 LIBNAME 语句;有各种特定于 Teradata 的选项可能会有所帮助。

标签: sas teradata


【解决方案1】:

我怀疑正在发生的事情是查询通过隐式传递被推回 Teradata,因此某些东西在 Teradata 中不起作用。您可能需要查询将总和显式转换为其他类型。

要查看到底发生了什么,请使用OPTIONS SASTRACE;从文档中建议尝试

options sastrace=',,,d' sastraceloc=saslog nostsuffix;

尽管您可能需要考虑一些选项。这将显示在 Teradata 中执行的确切查询。直接在 Teradata 中尝试相同的查询,看看是否可以防止它出现相同的问题。

一旦你弄清楚了,你就可以使用显式传递来执行正确的查询;即

proc sql;
 connect to teradata [options, same as on the libname usually];
 create table mydata as select * from connection to teradata (
   ... actual teradata syntax ...
 );
quit;

【讨论】:

    【解决方案2】:

    正如 Joe 之前指出的,我将调查导致此问题的潜在问题。但是,我找到了解决根本问题的快速解决方法。我将以下行用于我的SUM

    Round((SUM(myField))/1) format=13. 
    

    【讨论】:

      【解决方案3】:

      在这些操作系统情况下,导致“数字溢出”问题的始终是为 Teradata 表中的 val 列定义的数据类型。 (我假设val 被定义为Integer 类型,最多可以容纳 +/-21 亿)

      试试这个,

      proc sql;
        CREATE TABLE test AS 
          (SELECT
             YEAR(dt) AS yr,
             MONTH(dt) AS mo,
             SUM(cast(val as dec(32,0))) AS total
           FROM
             mydb1234.myTable
           WHERE
             myDate BETWEEN x AND y
           GROUP BY
             yr, mo);
      QUIT;
      

      在上面的代码中,SUM(cast(val as dec(32,0))) 首先将val 列转换(正式地)转换为可以容纳超过几十亿的数据类型,然后求和。 total 的总和列将是 dec(32,0),SAS 完全有能力处理如此大的数字。

      【讨论】:

      • 我认为这不会在 SAS 中编译,因为 cast 不是 SAS 函数,对吗?它可以在显式直通中工作。
      • 如果您将 SQL 作为传递(利用数据库处理)执行到 Teradata,则此答案中的 SQL 将直接在 Teradata 上运行。
      • 当然可以,但上面的答案并没有做到这一点。 :) 大多数时候“利用数据库处理”并不是很重要,因为 SAS 在很大程度上是这样做的(将 SAS 代码转换为数据库内处理);毕竟,这首先是让我们陷入麻烦的原因。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-18
      • 2011-12-08
      • 1970-01-01
      • 2019-11-16
      • 1970-01-01
      • 2012-02-14
      • 1970-01-01
      相关资源
      最近更新 更多