Как избежать исключения 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 и т. д., имеют формат DECIMAL(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), или
  • Предоставляет выражение/функцию для безопасного «умножения с безопасным от переполнения десятичным преобразованием»?
Если нет, является ли единственный надежный способ переписать все выражения и вставить явные приведения после каждого умножения/деления?
Точный код для воспроизведения проблемы:
import duckdb
import polars as pl

df = pl.DataFrame({"AMOUNT": 8760, "PRICE": 22.2131, "RATE": 1})
df = df.cast(pl.Decimal(scale=10))

result = duckdb.sql("""
FROM df
SELECT AMOUNT * PRICE * RATE * 1000
""").pl()

print(result)


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

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

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

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

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

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