0

ここで別の質問に答えるために、次のデータ構造と行を作成しました。

create table [resource] (Name varchar(16),date datetime, project varchar(16),hours int)
INSERT INTO resource
values ('Andy Sandy', '2013-03-02', 'Enhancements',40)
INSERT INTO resource
values('Fred Jones', '2013-10-02', 'Enhancements',40)

次のクエリを実行しました。

select 
case when sum(hours) > 0 Then
    CAST(SUM(hours) as DECIMAL(5,2))/40
else 0 end as [hours],
[DATE]
from resource group by date

結果は次のようになります。

Hours           Date
1.000000    2013-03-02 00:00:00.000
1.750000    2013-10-02 00:00:00.000

時間を小数にキャストするときに、精度を5、スケールを2に指定しました。なぜこのような数値なのかわかりません。精度とスケールを指定しない場合、結果は同じです。どうしてこれなの?

4

2 に答える 2

3

あなたはnumeric(5,2)/40をやっています。

精度、スケール、長さから

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

40numeric(2,0)は、精度とスケールを維持する可能な限り最小の10進表現であるとして扱います。

それで

p1=5
s1=2,
p2=2
s2=0

次に、それをBOLの数式に接続します

Precision: 5 - 2 + 0 + max(6, 2 + 2 + 1) = 9
Scale: max(6, 2 + 2 + 1)                 = 6

したがって、結果はnumeric(9,6)です。

これはからも見ることができます

;WITH cte(thing) AS
(
 SELECT CAST(1 as DECIMAL(5,2))/40
)
SELECT thing, 
       sql_variant_property(thing,'basetype') AS basetype,
       sql_variant_property(thing,'precision') AS precision, 
       sql_variant_property(thing,'scale') AS scale, 
       sql_variant_property(thing,'maxlength') AS maxlength
FROM cte

戻り値

+----------+----------+-----------+-------+-----------+
|  thing   | basetype | precision | scale | maxlength |
+----------+----------+-----------+-------+-----------+
| 0.025000 | decimal  |         9 |     6 |         5 |
+----------+----------+-----------+-------+-----------+

(注:decimalおよびnumericは同義語です)

于 2013-03-02T19:32:07.917 に答える
2

おかしいですね。sp_describe_first_result_setを実行する場合

sp_describe_first_result_set N'
select 
case when sum(hours) > 0 Then
    CAST(SUM(hours) as DECIMAL(5,2))/40
else 0 end as [hours],
[DATE]
from resource group by date'

返される時間列がdecimal(9,6)としてキャストされていることがわかります。

元のキャストをたとえばDECIMAL(10,6)に変更すると、(14,10)として再キャストされます。つまり、4レベルの小数点以下の精度が追加されるだけだと思います。完全ではありません!

仕切りを40.0から400.0に変更します-これで(15,11)としてキャストされます-仕切りの精度に基づいて、さらに高いレベルの精度が追加されます。

代わりに40.0000に変更してください(3つの余分なゼロ)-今は(20,15)です。そのため、元の値と除数の両方に基づいて精度を決定する関数が機能しています。

小数点以下の精度が上がるたびに、元のキャストに(2,1)が追加されます。左側のすべてのレベルの精度は、元のキャストに(1,1)を追加します。

時間の列をdecimal(5,2)として返すには、次のことを行う必要があります。

select 
case when sum(hours) > 0 Then
    CAST(SUM(hours) /40.0 as decimal(5,2))
else 0 end as [hours],
[DATE]
from resource group by date
于 2013-03-02T19:27:06.680 に答える