Вопрос

trying to understand why the end result of my query is return decimal(18,2) instead of decimal(18,3).

i know that sum will return decimal(38, s), and i know there is some data type precedence in terms of what results you return from a case statement, but i cant find any literature on the changing of scale within case statements when both returns decimal with different scale

why does the below query return decimal(38,2) instead of decimal(38,3)?

Note that i know how to fix this query, i'm more so interested as to why its not working in its current form.

Thanks.

CREATE TABLE supportContacts 
    (
PolicyNumber char(1),
LoadingRate decimal(18,2),
LoadingRate2 decimal(18,3)
    );

INSERT INTO supportContacts
(PolicyNumber, LoadingRate,LoadingRate2)
VALUES
('A', '15.52', '15.523'),
('B', '18.54', '15.525'),
('C', '1.25', '15.552');

select PolicyNumber
     , case when PolicyNumber = 'A' then sum(loadingrate2)
            else sum(LoadingRate)
            end

     from #supportContacts
group by PolicyNumber

SQL Fiddle link http://sqlfiddle.com/#!3/f4ecd

Это было полезно?

Решение

within case statements when both returns decimal with different scale

Not possible. A CASE expression computes a value. The data type of the value it produces is determined via the data type precedence rules, but the values it can return have to all be converted to a single data type.

As to why it selects (38,2) over (38,3), well, if it doesn't have enough bits available, it will always sacrifice scale over precision. See e.g. Precision, Scale and Length:

  • The result precision and scale have an absolute maximum of 38. When a result precision is greater than 38, the corresponding scale is reduced to prevent the integral part of a result from being truncated.

The datatypes produced by the SUM() calls are decimal(38,2) and decimal(38,3). We can then use the same rules as included in the above link to work out what CASE is going to do to determine its result type. The rules to follow are the ones specified for the e1 { UNION | EXCEPT | INTERSECT } e2 operation.

The result precision is given as max(s1, s2) + max(p1-s1, p2-s2) - which is max(2,3) + max(38-2, 38-3) - which is 3 + 36 which is 39. As stated, since the maximum precision is 38, we have to reduce the resultant scale.

Другие советы

You need to explicitly cast to decimal(18,3) when using case statement like --

select PolicyNumber , 
    case when PolicyNumber = 'A' then 
    CAST(sum(loadingrate2) AS DECIMAL(18,3))
    else CAST(sum(loadingrate) AS DECIMAL(18,3))
    end  AS LoadingRate
    from supportContacts
    group by PolicyNumber 
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top