2013-04-08 11 views
5

Mam następujący zestaw obliczeń w programie Excel, które chcę móc użyć w procedurze przechowywanej.precyzja SQL zmiennoprzecinkowa ograniczona do 6 cyfr

Excel

CellA: 45/448.2 = 0.100401606425703 
CellB: 1-CellA = 0.899598393574297 
CellC: 1-CellB = 0.100401606425703 
CellD: CellC * 448.2 = 45.000000000000000 

W SQL robie co następuje:

declare @a decimal(18,15) = 45/448.2 
declare @b decimal(18,15) = [email protected] 
declare @c decimal(18,15) = [email protected] 
declare @d decimal(18,15) = @c * 448.2 

Próbowałem również prowadzenie obliczeń w jednej linii

declare @e decimal(18,15) = (1-(1-(45/448.2)))*448.2 

kiedy wrócę SQL wartości daje mi następujące:

@a: 0.100401000000000 
@b: 0.899599000000000 
@c: 0.100401000000000 
@d: 44.999728200000000 

@e: 44.999728200000000 

Próbowałem dostosować precyzję liczb dziesiętnych w SQL, ale nic nie robi różnicy, zwraca tylko pierwsze 6 cyfr dziesiętnych.

Czy program Excel przeprowadza dowolną optymalizację podczas uruchamiania formuły?

Wszelkie pomysły?

+0

próbować, rzekli SELECT 45/CAST (448.2 AS DECIMAL (18,1)) '. [Linki tutaj] (http://stackoverflow.com/a/5385417/73226) mówią zasady dla wynikowego typu danych podziału. –

+0

@MartinSmith, który daje mi pełniejszy dziesiętny dla @a, chociaż moja odpowiedź to 45.000000000000085 czy jesteś w stanie wyjaśnić, dlaczego? – ScampDoodle

+0

Zostało to wyjaśnione w dwóch linkach z poprzedniej odpowiedzi, których byłem zbyt leniwy, aby odtworzyć powyższe. 'e1/e2 daje p = p1 - s1 + s2 + max (6, s1 + p2 + 1), s = max (6, s1 + p2 + 1)'. Jeśli 'p' będzie'> 38', to 's' jest obcięte w' 6' –

Odpowiedz

7

Nawet tylko pierwszą linię wystarczy, aby pokazać problem:

declare @a decimal(18,15) = 45/448.2 
print @a 

daje

--------------------------------------- 
0.100401000000000 

Wynika to z typów danych. Kiedy mówisz

448.2 

to (za the documentation) interpretować jako stałą typu decimal i also per the documentation,

W Transact-SQL, stała z przecinkiem jest automatycznie przekonwertowane na liczbową wartość danych, przy użyciu wymaganej precyzji i skali co najmniej . Na przykład, stały 12.345 jest przekształcono w wartości liczbowej z dokładnością do 5, a skalę 3.

Tak 448.2 jest decimal(4,3). 45 jest , która w połączeniu z decimalis treated as having precision of 10 and scale 0. Kiedy dzielimy, the rules powiedzieć

Operation  Result precision      Result scale 
e1/e2  p1 - s1 + s2 + max(6, s1 + p2 + 1)  max(6, s1 + p2 + 1) 

która w tym przypadku daje wynik 10 - 3 + 0 + max(6, 0 + 3 + 1) precyzję i skalę max(6, 0 + 3 + 1), który wychodzi do 13 i 6.

Ta skala wyników od 6 powoduje, że wynik zawiera tylko sześć miejsc po przecinku.

Rozwiązaniem problemu jest przekonwertowanie operandów na odpowiedni typ przed rozpoczęciem ich działania; na przykład, tutaj są dwa sposoby:

wymusić ilość należy traktować jako zmiennoprzecinkowych:

declare @a decimal(18,15) = 45/448.2e0 
select @a 

--------------------------------------- 
0.100401606425703 

Jawnie dostarczyć skalę dziesiętnych:

declare @a decimal(18,15) = 45/cast(448.2 as decimal(18,10)) 
select @a 

--------------------------------------- 
0.100401606425703 
+0

Ustawiło to mnie na właściwej ścieżce, musiałem dostosować liczbę miejsc dziesiętnych, ale ostatecznie była to właściwa odpowiedź – ScampDoodle