Как избежать исключения DuckDB OutOfRangeException при умножении десятичных чиселPython

Программы на Python
Ответить
Anonymous
 Как избежать исключения DuckDB OutOfRangeException при умножении десятичных чисел

Сообщение Anonymous »

Я работаю с DuckDB, и у меня есть несколько предоставленных клиентом SQL-выражений, в которых используются столбцы DECIMAL(38,10) (фиксированная точность с 10 цифрами после десятичной точки).
Например:

Код: Выделить всё

SELECT S1__AMOUNT * S1__PRICE * S1__UNITS * 1000
Все столбцы, такие как S1__AMOUNT, S1__PRICE и т. д., являются ДЕСЯТИЧНЫМИ (38,10).
При умножении нескольких таких столбцов (особенно трех или более) и затем умножении на константу (например, * 1000) я получаю:

Код: Выделить всё

duckdb.duckdb.OutOfRangeException: Out of Range Error:
Overflow in multiplication of DECIMAL(38) (194586756000000000000000000000000000 * 1000).
You might want to add an explicit cast to a decimal with a smaller scale.
Ограничения:
Я не могу привести к DOUBLE, но после каждой операции разрешено приводить ее результат к десятичному виду (38,10)
Я знаю, что могу вручную переписать предложение SQL для приведения после каждого шага, например:

Код: Выделить всё

CAST(
CAST(
CAST(S1__AMOUNT * S1__PRICE AS DECIMAL(38,10))
* S1__UNITS AS DECIMAL(38,10)
)
* 1000 AS DECIMAL(38,10)
)
Но поскольку предложения sql пишутся клиентом и могут быть довольно случайными, я не хочу использовать этот неуклюжий и подверженный ошибкам способ.
Вопрос:
Есть ли какой-нибудь способ настроить DuckDB так, чтобы он:
  • Автоматически уменьшал промежуточный десятичный масштаб/точность, если необходимо вписаться внутрь DECIMAL(38,10), без создания исключения OutOfRangeException, или
  • Автоматически приводит промежуточные арифметические результаты обратно к безопасному DECIMAL(38,10), или
  • Предоставляет выражение/функцию для безопасного «умножения с безопасным от переполнения десятичным продвижением»?
Если нет, то является ли это единственным надежным способом переписать все выражения и вставлять явные приведения после каждого умножения/деления?
Точный код для воспроизведения проблемы:

Код: Выделить всё

sql_ruleset_clause = """
SELECT AMOUNT * PRICE * RATE * 1000
FROM read_parquet('decimal_test.parquet')
"""
duckdb_connection = duckdb.connect(database=":memory:", read_only=False)
zxc = duckdb_connection.execute(sql_ruleset_clause).pl()
print(zxc)
где decimal_test.parquet содержит: {AMOUNT: 8760, PRICE: 22,2131, RATE: 1
важно: все столбцы типа decimal(38,10)

Подробнее здесь: https://stackoverflow.com/questions/798 ... g-decimals
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»