SQLServerの小数点から末尾のゼロを削除します


85

列があります。DECIMAL(9,6)つまり、999,123456のような値をサポートしています。

しかし、123,4567のようなデータを挿入すると、123,456700になります

それらのゼロを削除する方法は?


正解を@Andomarの回答に変更してください
dangalg 2018年

@dangalg:これは確かにプレゼンテーション層で行われるべきだと強く信じています。だから私は受け入れられた答えを決して変えませんでした。しかし、さらに検討した結果、コミュニティが明確に示した、どの回答が最良かを受け入れるべきだと思います。
abatishchev

回答:


147

Adecimal(9,6)は、コンマの右側に6桁を格納します。末尾のゼロを表示するかどうかはフォーマットの決定であり、通常はクライアント側で実装されます。

ただし、SSMSはfloat後続ゼロなしでフォーマットするdecimalため、 float:にキャストすることで後続ゼロを削除できます。

select 
    cast(123.4567 as DECIMAL(9,6))
,   cast(cast(123.4567 as DECIMAL(9,6)) as float)

プリント:

123.456700  123,4567

(私の小数点記号はコンマですが、SSMSは小数点をドットでフォーマットします。明らかに既知の問題です。)


8
+1 floatに変換すると結果が不正確になると思いましたが、まったく問題なく機能しているようです。
マーティンスミス

1
この方法の欠点の1つは、「2.0」から始めると「2」に変わることです。これは質問をする人にとってはおそらく問題ありませんが、他の後続ゼロを保持せずに、小数点以下の単一のゼロを保持できる必要がありました。@ user1959416の答えはそれを解決します。
Mason G. Zhwiti 2013年

6
プラスフロートは一般的に、数値を格納するための非常に悪い選択です。正確なタイプではないため、丸め誤差が発生します。フロートは絶対に使用しないでください。
HLGEM 2013

末尾のゼロなしでフォーマットされているフロートに関するコメントは非常に役に立ちました
Sanjiv Jivan 2016年

小数のスケールと精度は浮動小数点のスケールと精度を超える可能性があるため、(17桁を超える重要度で)この答えがうまくいかない場合があると思いますが、私は正しいですか?
CaiusJard18年

32

FORMAT()関数(SqlAzureおよびSql Server 2012+)を使用できます。

SELECT FORMAT(CAST(15.12     AS DECIMAL(9,6)), 'g18')  -- '15.12'
SELECT FORMAT(CAST(0.0001575 AS DECIMAL(9,6)), 'g10')  -- '0.000158'
SELECT FORMAT(CAST(2.0       AS DECIMAL(9,6)), 'g15')  -- '2'

FLOAT(またはREAL)で使用する場合は注意してください。マシン表現の精度が制限されていると望ましくない影響が生じるため、使用しないでください(またはREALではg17それg8以上)。

SELECT FORMAT(CAST(15.12 AS FLOAT), 'g17')         -- '15.119999999999999'
SELECT FORMAT(CAST(0.9 AS REAL), 'g8')             -- '0.89999998'
SELECT FORMAT(CAST(0.9 AS REAL), 'g7')             -- '0.9'

さらに、ドキュメントによると、次の点に注意してください。

FORMATは、.NET Framework共通言語ランタイム(CLR)の存在に依存しています。この関数は、CLRの存在に依存するため、リモート化されません。CLRを必要とする関数をリモート処理すると、リモートサーバーでエラーが発生します。

SqlAzureでも動作します。


私の目的のために、g8のフォーマット文字列が私の番号を「1e-08」としてフォーマットしているのを見つけました。これは私が求めていたものではありませんでした。この答えは、私が使用できるものに私を導きました
Caius Jard 2018年

18
SELECT CONVERT(DOUBLE PRECISION, [ColumnName])

SQL Server 2008以降
Bat_Programmer 2015年

番号が「123.10705000000」の場合はどうなりますか?SELECT CONVERT(DOUBLE PRECISION、123.10705000000)を試してみましたが、答えとして「123.107」が表示されます。「123.10705」を出力したいですか?方法はありますか?CHARINDEXは使いたくない。
Bhavika Zimbar 2016年

16

floatが表すことができるよりも多くの桁が小数に含まれる可能性があるため、floatにキャストすることには消極的でした。

FORMAT 標準の.net形式の文字列 'g8'を使用すると、小数点以下が非常に小さい場合(1e-08など)に科学的記数法が返されますが、これも不適切でした。

カスタムフォーマット文字列(https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-numeric-format-strings)を使用すると、目的を達成できました。

DECLARE @n DECIMAL(9,6) =1.23;
SELECT @n
--> 1.230000
SELECT FORMAT(@n, '0.######')
--> 1.23

数値の末尾にゼロを少なくとも1つ含めて、2.0が2にならないようにする場合は、次のようなフォーマット文字列を使用します。 0.0#####

小数点はローカライズされているため、小数点記号としてコンマを使用するカルチャでは、コンマ出力が発生します。です

もちろん、これはデータレイヤーにフォーマットを実行させるというお勧めできない方法です(ただし、私の場合、他のレイヤーはありません。ユーザーは文字通りストアドプロシージャを実行し、結果を電子メールに入れています:/)


はい、これは、科学的記数法を避けながら、小数点の右側の数値を完全に制御できる唯一のソリューションです。このソリューションの唯一の問題は、FORMATが本当に(!)遅いことです。(SQL2019ではまだ..)
Tor

7
SELECT REVERSE(ROUND(REVERSE(2.5500),1))

プリント:

2.55

2
この方法は、ゼロしかない場合に後続のゼロをオンのままにするという点で優れています。だから、2.5500リターン2.55、および2.000リターン2.0ではなく、あなたが車でエンジンのサイズをフォーマットしているとき2.グレートより...
メイソンG. Zhwiti

4
@ MasonG.Zhwitiたとえば、232.3322000300200のように、小数点以下の桁数が多い小数でこれが機能するかどうかは疑問です:-)
gotqn 2013年

@gotqn良い点、それは間違いなく失敗します。ただし、特定のユースケース(自動車のエンジンサイズのフォーマット)では、完全に機能します。:)
Mason G. Zhwiti 2013年

@gotqnが言ったように..数が長いとバグがあります
Ofear 2013

これは、0.56000のような数値では正確に機能しません。それは56をもたらすでしょう。おかしい
Gunjan Shakya 2018


4

これを試して :

SELECT REPLACE(TRIM(REPLACE(20.5500, "0", " ")), " ", "0")

20.55を与える


1
REPLACE(TRIM(REPLACE(20.00、 "0"、 ""))、 ""、 "0")は、末尾に。を残します。=>「20」
キースサーモンズ2014年

それは私の場合に完全に適用可能であり、最も簡単な解決策のようです。親指と投票!
Oak_32605 4819

フロートに変換する必要のない素晴らしいソリューション!発見された1つの小さな問題がに0.000なりました.。これがSELECT REPLACE(RTRIM(REPLACE(20.5500, "0", " ")), " ", "0")後続ゼロのみをトリムするための修正です
wilson 2010

2

同様の問題がありましたが、小数点が存在しない小数点を削除する必要もありました。これは、小数点をそのコンポーネントに分割し、小数点文字列から取得する文字数を次の長さに基づいて計算するソリューションです。分数成分(CASEを使用しない)。さらに興味深いことに、私の数値は小数点なしの浮動小数点数として格納されていました。

DECLARE @MyNum FLOAT
SET @MyNum = 700000
SELECT CAST(PARSENAME(CONVERT(NUMERIC(15,2),@MyNum/10000),2) AS VARCHAR(10)) 
+ SUBSTRING('.',1,LEN(REPLACE(RTRIM(REPLACE(CAST(PARSENAME(CONVERT(NUMERIC(15,2),@MyNum/10000),1) AS VARCHAR(2)),'0',' ')),' ','0'))) 
+ REPLACE(RTRIM(REPLACE(CAST(PARSENAME(CONVERT(NUMERIC(15,2),@MyNum/10000),1) AS VARCHAR(2)),'0',' ')),' ','0') 

結果は痛いです、私は知っています、しかし私は上記の答えから多くの助けを借りてそこに着きました。


2

精度が低下する可能性があるため、変換する前にFLOATまたはMONEYに変換しないのが最善の方法です。したがって、安全な方法は次のようになります。

CREATE FUNCTION [dbo].[fn_ConvertToString]
(
    @value sql_variant
)
RETURNS varchar(max)
AS
BEGIN
    declare @x varchar(max)
    set @x= reverse(replace(ltrim(reverse(replace(convert(varchar(max) , @value),'0',' '))),' ',0))

    --remove "unneeded "dot" if any
    set @x = Replace(RTRIM(Replace(@x,'.',' ')),' ' ,'.')
    return @x
END

ここで、@ valueは任意のdecimal(x、y)にすることができます


@ abatishchev、fn_はSQL関数の優先プレフィックスであり、プレフィックスは標準のコーディングと命名規則、およびベストプラクティスで使用され、プレフィックスをカスタマイズできますが、ベストプラクティスではsp_、ストアドプロシージャ、fn_関数、tblテーブルなどに使用します。 on ...これは必須ではありませんが、データベースを整理するためのベストプラクティスです。
japzdivino 2016年

@japongskie:申し訳ありませんが、違います。プレフィックスはまったく必要ありません。これは実際には最悪の慣行です。参照してくださいmsdn.microsoft.com/en-us/library/dd172115(v=vs.100).aspx sqlperformance.com/2012/10/t-sql-queries/sp_prefix dba.stackexchange.com/q/25348/3186とさらに多く
abatishchev 2016年

@abatishchev、ああ、なるほど..だから私はもう学校の教えに従わない..ハハLOL、あなたのリンクはmdsnから来たので、これに感謝します、私は今私のベストプラクティスを変更します.. :)
japzdivino

2

同様の問題があり、次のような数値から後続ゼロをトリミングする必要がありました xx0000,x00000,xxx000

私が使用した:

select LEFT(code,LEN(code)+1 - PATINDEX('%[1-Z]%',REVERSE(code))) from Tablename

コードは、トリミングする番号が付いたフィールドの名前です。これが他の誰かに役立つことを願っています。


このコメントは、SQLServerのTRIMまたはFORMAT組み込み関数を使用できないほど古いバージョンのSQLServerを使用している場合にうまく機能します。
デヴィッド・Parvin

私はこの答えに1つの問題を見つけました。「コード」フィールドの値が「10」のようなものである場合、「1」を返します。数値が「10.00」の場合、小数点も無視されると思います。
DavidParvin19年

1

別のオプション...

これがどれほど効率的かはわかりませんが、機能しているようで、floatを経由しません。

select replace(rtrim(replace(
       replace(rtrim(replace(cast(@value as varchar(40)), '0', ' ')), ' ', '0')
       , '.', ' ')), ' ', '.')

真ん中の線は末尾のスペースを取り除き、外側の2つは小数点がない場合はポイントを削除します


1

小数の末尾のゼロを削除して、先頭のみで特定の長さの文字列を出力できるようにする必要がありましたゼロ

(たとえば、142.023400が000000142.0234になるように14文字を出力する必要がありました)、

私が使用されparsenamereverseそしてcast as int後続のゼロを削除するには:

SELECT
    PARSENAME(2.5500,2)
    + '.'
    + REVERSE(CAST(REVERSE(PARSENAME(2.5500,1)) as int))

(次に、先行ゼロを取得するために、上記の長さに基づいて正しい数のゼロを複製し、これを上記の前に連結することができます)

これが誰かに役立つことを願っています。


@Protiguous小数点が1つあるため、2.5500は<schema_name>。<object_name>のように読み取られます。2の2番目のパラメーターはスキーマ名を返し、1の2番目のパラメーターはオブジェクト名を返します。通常、dboを返すにはPARSENAME( 'dbo.TableName'、2)のように使用され、TableNameを返すにはPARSENAME( 'dbo.TableName'、1)のように使用されます。
アリ

こんにちは..あなたのコメントで私のエイリアスにフラグが付けられているようです。何故かはわからない?
連続

2020年5月26日にあなたが私に尋ねた正確な質問は、「PARSENAMEはここでどのように機能するはずですか?」でした。申し訳ありませんが、返信に時間がかかりました。
アリ

1

TSQLで先頭と末尾のゼロを削除することが可能です

  1. 文字列でない場合は、STR TSQL関数を使用して文字列に変換し、次に

  2. 先頭と末尾の両方のゼロを削除します

    SELECT REPLACE(RTRIM(LTRIM(REPLACE(AccNo,'0',' '))),' ','0') AccNo FROM @BankAccount
    
  3. フォーラムの詳細情報。


4
少し醜いですが、このバージョンは残り物を殺します '。':REPLACE(RTRIM(REPLACE(REPLACE(RTRIM(REPLACE(X,'0',' ')),' ','0'),'.',' ')),' ','.')
Chris B

1
数値が10進数でない場合は、ゼロもトリミングされるので注意してください。CHARINDEX( '。'、@ Number)!= 1はそれをテストします。
Muflix 2015

以前の小切手が間違っています。Len(@Test)-Len(Replace(@ Test、 'a'、 ''))As NumberOfCharacters Explained:tinyurl.com/o4fc8g7 and tinyurl.com/kgzkuqk
Muflix

0

これはどう?@thisDataとして関数に入るデータを想定します。

BEGIN
  DECLARE @thisText VARCHAR(255)
  SET @thisText = REPLACE(RTRIM(REPLACE(@thisData, '0', ' ')), ' ', '0')
  IF SUBSTRING(@thisText, LEN(@thisText), 1) = '.'
    RETURN STUFF(@thisText, LEN(@thisText), 1, '')
  RETURN @thisText
END

0
case when left(replace(ltrim(rtrim(replace(str(XXX, 38, 10), '0',  ' '))), ' ', '0'), 1) = '.'
then '0' 
else ''
end +

replace(ltrim(rtrim(replace(str(XXX, 38, 10), '0',  ' '))), ' ', '0') +

case when right(replace(ltrim(rtrim(replace(str(XXX, 38, 10), '0',  ' '))), ' ', '0'), 1) = '.'
then '0' 
else ''
end

これも数字の間の0(ゼロ)を置き換えませんか?いけないただ...端で働く置き換える考える
MTK

0

これは古い投稿であることを理解していますが、私が思いついたSQLを提供したいと思います

DECLARE @value DECIMAL(23,3)
set @value = 1.2000
select @value original_val, 
    SUBSTRING(  CAST( @value as VARCHAR(100)), 
                0,
                PATINDEX('%.%',CAST(@value as VARCHAR(100)))
            )
      + CASE WHEN ROUND( 
                        REVERSE( SUBSTRING( CAST(@value as VARCHAR(100)),
                                        PATINDEX('%.%',CAST(@value as VARCHAR(100)))+1,
                                        LEN(CAST(@value as VARCHAR(100)))
                                        )
                                )
                    ,1) > 0 THEN 
            '.' 
            +  REVERSE(ROUND(REVERSE(SUBSTRING( CAST(@value as VARCHAR(100)),
                                                PATINDEX('%.%',CAST(@value as VARCHAR(100)))+1,
                                                LEN(CAST(@value as VARCHAR(100)))
                                                )
                ),1))
        ELSE '' END  AS modified_val


0

最も簡単な方法は、値をFLOATとしてキャストしてから、文字列データ型にキャストすることです。

CAST(CAST(123.456000 AS FLOAT) AS VARCHAR(100))

-1

これを試して:

select Cast( Cast( (ROUND( 35.457514 , 2) *100) as Int) as float ) /100

値を変更しないので、ここでは@ user1959416の回答の方が適しています。たとえば、2.5550から開始すると、メソッドの結果は2.56になりますが、メソッドの結果は2.555になります。
Mason G. Zhwiti 2013年

-1

このスレッドは非常に古いことは知っていますが、SQL Server 2012以降を使用していない場合、または何らかの理由でFORMAT関数を使用できない場合は、次のように機能します。

また、数が1未満の場合(例:0.01230000)、多くのソリューションが機能しませんでした。

以下は負の数では機能しないことに注意してください。

DECLARE @num decimal(28,14) = 10.012345000
SELECT PARSENAME(@num,2) + REPLACE(RTRIM(LTRIM(REPLACE(@num-PARSENAME(@num,2),'0',' '))),' ','0') 

set @num = 0.0123450000
SELECT PARSENAME(@num,2) + REPLACE(RTRIM(LTRIM(REPLACE(@num-PARSENAME(@num,2),'0',' '))),' ','0') 

それぞれ10.012345と0.012345を返します。


-1

これを試して:

select isnull(cast(floor(replace(rtrim(ltrim('999,999.0000')),',','')) as int),0)

これはを返し999999、OPは後続のゼロを削除するように要求しています。
japzdivino 2016年

-1

DECIMAL(9,6)列は、精度を失うことなくfloatに変換されるため、CAST(... AS float)でうまくいきます。


@HLGEM:フロートは数値を保存するのに不適切な選択であり、「フロートを使用しない」は正しくありません。たとえば、温度測定はフロートとしてうまくいくので、数値を知っている必要があります。

@abatishchevおよび@japongskie:SQLストアドプロシージャおよび関数の前にプレフィックスを付けることは、必要でない場合でも良い考えです。あなたが言及したリンクは、使用すべきでないストアドプロシージャに「sp_」プレフィックスを使用しないように指示するだけです。他のプレフィックス(「usp_」や「spBob_」など)は問題ありません。

参照:「小数点以下6桁以下のすべての整数は、精度を失うことなくIEEE 754浮動小数点値に変換できます」:https//en.wikipedia.org/wiki/Single-precision_floating-point_format

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.