2013-07-25 5 views
5

Я работал с запросом SQL SAS proc и обнаружил что-то странное. Во-первых, я попробовал этот простой запрос:Нечетное поведение на сумме (получение числового переполнения)

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 создать таблицу, используя длину поля, которая может поддерживать мои общие значения? Они находятся в миллиардном сотне миллиардов, поэтому я ничего не думаю об этом необычном. Мне было любопытно посмотреть, что вы, ребята, подумали.

+0

Это не проблема SAS, я не думаю. SAS не даст вам переполнения; если вы не в таких безумных цифрах, что это не может быть сохранено неточно в 64 битах, так или иначе, что, безусловно, не так. Если вы создали несколько значащих цифр> 15 значащих цифр, это может привести к значительным потерям, но это не даст вам никаких указаний на это. – Joe

+0

Как работает интерфейс с терадатой? Есть ли 'libname' на сервере teradata, или он проходит через или что-то еще? – Joe

+0

Там есть библиотека, и я ссылаться на него, как это: 'ОТ mydb1234.myTable' Где mydb1234 является' libref' –

ответ

1

Я собираюсь исследовать основные проблемы, вызвавшие эту проблему, как указал Джо ранее. Однако я нашел быстрое решение, которое решает проблему с корнем. Я использовал следующую строку для моего SUM

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

Я подозреваю, что происходит то, что запрос возвращается на 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; 
+0

Это имеет смысл, я дам ему попробовать, спасибо! –

0

В этих добрых бя ситуации всегда типа данных, которые были определены для val столбца в таблице Teradata, которая вызывает проблему «Числовое переполнение». (Я принимаю val определяется как Integer типа, который может содержать Шифрование до +/-) 2.1billion

попробовать это,

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 более чем способен обрабатывать такие большие числа.

+0

Я не думаю, что это скомпилировалось бы в SAS, так как приведение не является функцией SAS, не так ли? Это будет работать в явной сквозной форме. – Joe

+0

Если вы выполняете SQL как пропуск через (используя обработку базы данных) в Teradata, SQL в этом ответе будет выполняться непосредственно на Teradata. –

+0

Конечно, но вышеприведенный ответ этого не делает. :) В большинстве случаев «использование в обработке базы данных» не так важно, поскольку SAS в значительной степени это делает (преобразует код SAS в обработку в базе данных); что в конце концов это то, что нас беспокоит в первую очередь здесь. – Joe