1
SET COUNTDECIMALPLACES =  
    CASE Charindex('.', NEWNUMBER)
        WHEN 0 THEN 0
        ELSE
          LEN(
            CAST(
                 CAST(
                    REVERSE( NEWNUMBER ) AS float
                     ) AS bigint
                ) 
           )
    END   

数値が 222.9375 の場合、COUNTDECIMALPLACES = 3 と誤って表示されます。しかし、数値が 17.5548 の場合、COUNTDECIMALPLACES = 4 と正しく表示されます。理由を知っている人はいますか?

編集 1: コメントの質問に答えるには、SQL Server 2008 (MS) を使用しています。Gordon Linoff が私と同じエラーを受け取ったようです。また、NEWNUMBER のデータ型は float です。浮動小数点があることを考えると、私の最終的な目標は、小数点以下の桁数を数えることです。

4

1 に答える 1

2

222.9375 に対して 3 を取得しました。これREVERSEは、文字列式を受け入れるためです。float を渡すことにより、SQL Server は float から varchar への暗黙的な変換を行う必要があります。

Books Online によると:

CAST と CONVERT (Transact-SQL)

float および real スタイル
expression が float または real の場合、style は次の表に示す値のいずれかになります。その他の値は 0 として処理されます。


0 (デフォルト)

出力
A 最大 6 桁。適切な場合は、科学表記で使用します。

上記の定義は、以下の例を使用して視覚化できます。

declare @a float = 222.9375, @b float = 12.34564, @c float = 1234564.123456
select convert(varchar, @a, 0) -- Returns 222.938 -- Notice only 6 digits are displayed
    , convert(varchar, @b, 0) -- Returns 12.3456 -- Notice only 6 digits are displayed
    , convert(varchar, @c, 0) -- Returns 1.23456e+006 -- Notice only 6 digits are displayed

floatfloat をデータ型として使用し続けると、文字列操作にキャストしvarcharて実行しても、探している正確な数値を取得することは期待できません。

小数に割り当てる小数点以下の桁数 (スケール) がわからないため、単純にキャストすることさえできませんfloatdecimal

または、データ型として decimal で開始すると、数値を宣言する必要があるため、数値の小数点以下の桁数が自動的にわかります。

例えば

declare @number decimal(19, 4) = 222.9375
select @number -- 222.9375

さらに一歩進めましょう。ある種の計算の後でスケール (小数点以下の桁数) を計算するには、以下の関数を使用して答えを得ることができます。

declare @newnumber decimal(19, 4) = 222.9375    

select @newnumber * @newnumber -- Returns 49701.1289063
    , sql_variant_property(@newnumber * @newnumber, 'scale') -- Returns 7

ただし、使用するデータ型を制御できない可能性が最も高いです。私が考えることができる 1 つの方法は、両方の使用法を組み合わせて、decimal目的varcharを達成することです。

declare @newnumber float = 222.9375

-- The first 6 columns are just the working steps, solution is in the last column.
select 
    @newnumber as 'original'
    , cast(@newnumber as decimal(38, 18)) as 'decimal' -- Assuming all your numbers can fit in decimal(38, 18).
    , cast(cast(@newnumber as decimal(38, 18)) as varchar(max)) as 'varchar'
    , reverse(cast(cast(@newnumber as decimal(38, 18)) as varchar(max))) as 'reverse'
    , cast(reverse(cast(cast(@newnumber as decimal(38, 18)) as varchar(max))) as decimal(38, 0)) as 'decimal'
    , len(cast(reverse(cast(cast(@newnumber as decimal(38, 18)) as varchar(max))) as decimal(38, 0))) as 'len'

    , case charindex('.', @newnumber)
        when 0 then 0
        else len(cast(reverse(cast(cast(@newnumber as decimal(38, 18)) as varchar(max))) as decimal(38, 0)))
    end as 'All In One Step'
于 2013-05-09T04:53:15.223 に答える