Агрегирование по varchar, приведенному к десятичному, не дает правильного ответа - PullRequest
1 голос
/ 07 марта 2012

Недавно у нас возникла проблема с генерацией отчетов, в которой была выполнена агрегация (SUM()) для значений varchar. Эти значения хранятся в человеко-часах и являются целочисленными значениями, например: 456.9. Поскольку мы находимся в ведении, невозможно изменить дизайн стола. После некоторых исследований я изменил запрос, добавив явное приведение.

select ts.changedto as CHANGEDSTATE,
    cast(sum(coalesce(cast(trim(tw.estimatedhours) AS DECIMAL(5,2)),0)) AS UNSIGNED) as ESTIMATEDHOURS,        
    cast(sum(coalesce(cast(trim(tw.actualhours) AS DECIMAL(5,2)),0)) AS UNSIGNED) as ACTUALHOURS
    from tstatechange ts
                  left outer join tworkitem tw on (ts.workitemkey=tw.workitemkey)
                       left outer join tprojcat pc on (tw.prOJCATKEY = pc.pKEY)
                             where (ts.changedto = '8') and ts.lastedit between '2012-02-01  00:00:00' and '2012-02-28 23:59:59'
                                   and pc.projkey = 39 group by CHANGEDSTATE;

Даже этот запрос возвращает неправильные значения. Например для этих значений ручное суммирование

(89.35
96
11.15
0
0.1
92
1
609.05
61.25
0.5
1
0.5) 

дает 961,9, а запрос возвращает 963. Может ли кто-нибудь помочь мне с этим. Есть ли какие-то специальные функции или какие-либо другие обходные пути?

Ответы [ 2 ]

0 голосов
/ 07 марта 2012

Вы не упомянули, какой сервер SQL вы используете, но я не могу повторить это на MS SQL Server 2008R2. Вы уверены, что ваш запрос возвращает данные, которые вы перечислили?

select '89.35' as x
into #tmp
union all select '96'
union all select '11.15 '
union all select null 
union all select '0.10 '
union all select '92.00 '
union all select '1.00 '
union all select '609.05'
union all select '61.25 '
union all select '0.50'
union all select '1 '
union all select '0.50 '


select sum(coalesce(cast(ltrim(rtrim(x)) AS DECIMAL(5,2)),0))
from #tmp  -- Yields 961.9

select cast(sum(coalesce(cast(ltrim(rtrim(x)) AS DECIMAL(5,2)),0)) AS INT)
from #tmp  -- Yields 961

select 89.35+96.0+11.15+0.0+0.1+92.0+1.0+609.05+61.25+0.5+1.0+0.5 -- Yields 961.9

SQL Server не имеет типа UNSIGNED, поэтому я использовал INT.

0 голосов
/ 07 марта 2012

Я думаю, что ваш запрос страдает от округления. Эти два 0,5, вероятно, станут двумя 1. давая 963. Какую базу данных вы используете?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...