«Уменьшить» тип десятичных данных sql до наименьшей точности и масштабировать в зависимости от значения - PullRequest
3 голосов
/ 15 июня 2011

Я работаю над проблемой, связанной со многими sql десятичными умножениями, используя довольно высокую точность.

Недавняя ошибка побудила меня провести некоторое исследование, и я натолкнулся на унизительную статью (http://msdn.microsoft.com/en-us/library/ms190476.aspx) о том, как вычисляются точность и масштаб десятичного результата.

Насколько я понимаю, чтобы избежать усечения или неожиданного округления, иногда необходимо приводить операнды и, возможно, промежуточные вычисления к размерам, которыебудет работать и давать желаемые результаты. Каждый операнд дается мне как десятичное число (19,5). Я ничего не могу с этим поделать, так как мы поддерживаем такой широкий диапазон значений.

Myвопрос : Могу ли я уменьшить / привести тип этих десятичных (19,5) значений «на лету» к наименьшему десятичному типу (точность и масштаб), который будет содержать значение?

Например, могу ли я привести эту переменную (@Cw) к десятичной (4,1) «на лету», прежде чем она будет использована в моем умножении?

DECLARE @Cw decimal(19,5)
SET @Cw = 113.5

--Some type of CAST, i.e.
--CAST(@Cw as DECIMAL(GetActualPrecision(@Cw), GetActualScale(@Cw)))

-–should show 4 instead of 19
SELECT SQL_VARIANT_PROPERTY(@NewCw, 'Precision') 

–-should show 1 instead of 5
SELECT SQL_VARIANT_PROPERTY(@NewCw, 'Scale')

Спасибо!

Ответы [ 2 ]

3 голосов
/ 15 июня 2011

Нет

Динамического CAST нет: масштаб и точность статичны: «фиксированная точка»
Если вы хотите произвольную точность, используйте float, который, конечно, является «плавающей точкой»

В основном мы используем десятичную дробь и у нас нет проблем.

Если у вас сложные математические вычисления, которые работают не очень хорошо, я бы подумал об использовании CLR в SQL или в коде клиента, который имеет лучшие библиотеки

0 голосов
/ 03 июля 2018

У меня была такая же проблема, и я решил ее с помощью CLR. Следующая функция C # «упаковывает» десятичный тип с наименьшей возможной точностью и масштабом.

internal static SqlDecimal PackPrecScale(SqlDecimal d)
{
    //Remove leading zeros
    var s = d.ToString();
    var l = s.Length;
    var indexofperiod = s.IndexOf('.');

    //Remove trailing zeros
    if (indexofperiod != -1)
    {
        while (s[l - 1] == '0') l--;
        if (s[l - 1] == '.')
        {
            l--;
            indexofperiod = -1;
        }
    }

    var precision = 6;
    var scale = 0;
    if (l > 0)
    {
        precision = l;
        if (s[0] == '-') precision--;
        if (indexofperiod != -1)
        {
            precision--;
            scale = l - indexofperiod - 1;
        }
        if (precision < 6) precision = 6;
    }

    return SqlDecimal.ConvertToPrecScale(d, precision, scale);
}
...