SQL Server의 십진수에서 후행 0 제거


85

DECIMAL(9,6)999,123456과 같은 값을 지원 하는 열이 있습니다 .

하지만 123,4567과 같은 데이터를 삽입하면 123,456700이됩니다.

그 0을 제거하는 방법?


Andomar의 대답 @에 정답을 변경하십시오
dangalg

@dangalg : 저는 이것이 실제로 프레젠테이션 레이어에서 이루어져야한다고 강력하게 믿습니다. 그래서 내가 받아 들인 대답을 변경하지 않았습니다. 그러나 더 깊이 고려한 후에 커뮤니티에서 어떤 답변이 가장 좋은지 명확하게 표시 한 것을 수락해야한다고 생각합니다.
abatishchev

답변:


147

A decimal(9,6)는 쉼표 오른쪽에 6 자리 숫자를 저장합니다. 후행 0을 표시할지 여부는 일반적으로 클라이언트 측에서 구현되는 형식 지정 결정입니다.

그러나 SSMS는 float후행 0이없는 형식이므로 decimal를 a 로 캐스트하여 후행 0을 제거 할 수 있습니다 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로 변환하면 결과가 부정확해질 것이라고 생각했지만 완전히 잘 작동하는 것 같습니다.
Martin Smith

1
이 방법의 한 가지 단점은 "2.0"으로 시작하면 "2"로 바뀐다는 것입니다. 이것은 질문을하는 사람에게는 괜찮을 것입니다. 그러나 저는 다른 후행 0을 유지하지 않고 소수점 뒤에 하나의 0을 유지할 수 있어야했습니다. @ user1959416의 답변으로 해결됩니다.
Mason G. Zhwiti

6
일반적으로 플러스 플로트는 숫자를 저장하는 데 매우 적합하지 않습니다. 정확한 유형이 아니므로 반올림 오류가 발생합니다. float를 사용하지 마십시오.
HLGEM

수레에 대한 코멘트는 후행 제로 않고 매우 유용하고 포맷하는
Sanjiv Jivan을

소수의 규모와 정밀도가 부동 소수점을 초과 할 수 있으므로 (17 자리 이상의 의미있는)이 답변이 작동하지 않는 경우가있을 수 있다고 생각하는 것이 맞습니까?
Caius Jard

31

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)와 함께 사용할 때는주의하십시오. g17또는 더 크게 (또는 g8REAL과 함께 또는 더 크게) 사용하지 마십시오 . 기계 표현의 제한된 정밀도로 인해 원하지 않는 효과가 발생하기 때문입니다.

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"로 형식화 한 것을 발견했습니다. 이 답변은 내가 생각 사용할 수있는 일에 저를지도 않았다
카이 우스 JARD

17
SELECT CONVERT(DOUBLE PRECISION, [ColumnName])

SQL Server 2008 이상
Bat_Programmer 2015-06-23

번호가 "123.10705000000"이면 어떻게 되나요? SELECT CONVERT (DOUBLE PRECISION, 123.10705000000)로 시도했지만 대답으로 "123.107"이 표시됩니다. 출력으로 "123.10705"를 원하십니까? 방법이 있습니까? CHARINDEX를 사용하고 싶지 않습니다.
Bhavika Zimbar

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

숫자 뒤에 0이 하나 이상 있어야하므로 2.0이 2가되지 않도록하려면 다음과 같은 형식 문자열을 사용하십시오. 0.0#####

소수점은 지역화되어 있으므로 쉼표를 소수점 구분 기호로 사용하는 문화권에서는. 이다

물론 이것은 데이터 레이어가 형식을 지정하는 것은 좋지 않습니다. (하지만 제 경우에는 다른 레이어가 없습니다. 사용자는 말 그대로 저장 프로 시저를 실행하고 결과를 이메일에 넣습니다 : /)


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

인쇄물:

2.55

2
이 방법은 0 만 있으면 후행 0을 남겨 두는 점에서 좋습니다. 그래서 2.5500 수익률 2.55 및 2.000 수익률 2.0보다는 당신이 차량에 엔진 크기를 포맷 할 때 2. 대 이상의 ...
메이슨 G. Zhwiti

4
@ MasonG.Zhwiti 나는 이것이 232.33220003200과 같은 소수점 뒤에 더 많은 자릿수를 가진 소수와 함께 작동 할 것이라고 의심한다 :-)
gotqn

@gotqn 좋은 지적, 확실히 실패합니다. 그러나 특정 사용 사례 (자동차의 엔진 크기 형식 지정)의 경우 완벽하게 작동합니다. :)
Mason G. Zhwiti

@gotqn 말했듯이 숫자가 긴 경우 ... 그것은 버그입니다
Ofear

0.56000과 같은 숫자에는 정확히 작동하지 않습니다. 그것은 (56) 재미 얻을 것
Gunjan 샤카족


3

이 시도 :

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

20.55 제공


1
REPLACE (TRIM (REPLACE (20.00, "0", "")), "", "0")은 뒤에. => "20."
Keith Sirmons 2014 년

제 경우에 완벽하게 적용 할 수 있으며 가장 간단한 솔루션 인 것 같습니다. 엄지와 투표!
Oak_3260548

플로트로 변환 할 필요가없는 훌륭한 솔루션! 발견 된 사소한 문제 0.000.. 여기에 SELECT REPLACE(RTRIM(REPLACE(20.5500, "0", " ")), " ", "0")후행 0 만 트리밍 하는 수정 사항 이 있습니다
wilson

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 될 수있는 임의의 소수 (X, Y)


@abatishchev, fn_은 SQL 함수에 대한 기본 접두사이며 접두사는 표준 코딩 및 명명 규칙과 모범 사례에 사용되며 접두사를 사용자 지정할 수 있지만 모범 사례의 sp_경우 저장 프로 시저, fn_함수, tbl테이블 등에 사용합니다. on ... 이것은 필수 사항은 아니지만 데이터베이스를 구성하는 모범 사례입니다.
japzdivino

@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

@abatishchev, 오, 알겠습니다 .. 그래서 더 이상 학교의 가르침을 따르지 않을 것입니다 .. haha ​​LOL, 귀하의 링크가 mdsn에서 왔기 때문에, 이것에 대해 감사합니다. 이제 내 모범 사례를 변경하겠습니다 .. :)
japzdivino

2

비슷한 문제가 있었는데, 다음과 같은 숫자에서 후행 0을 잘라 내야했습니다. xx0000,x00000,xxx000

나는 다음을 사용했다 :

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

코드는자를 번호가있는 필드의 이름입니다. 이것이 다른 사람에게 도움이되기를 바랍니다.


이 주석은 SQL Server의 함수에서 TRIM 또는 FORMAT 빌드를 사용할 수 없을 정도로 오래된 SQL Server 버전을 사용하는 경우 잘 작동합니다.
David Parvin

이 답변에서 한 가지 문제를 찾았습니다. 'code'필드의 값이 '10'과 같은 경우 '1'을 반환합니다. 숫자가 '10 .00 '이면 소수점도 무시한다고 생각합니다.
David Parvin

1

다른 옵션 ...

이것이 얼마나 효율적인지 모르겠지만 작동하는 것처럼 보이고 float를 통해 가지 않습니다.

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

중간 선은 후행 공백을 제거하고 바깥 쪽 두 개는 소수점이없는 경우 점을 제거합니다.


1

내 소수에서 후행 0을 제거하여 선행 0 만있는 특정 길이의 문자열을 출력 할 수 있어야했습니다.

(예 : 142.023400이 000000142.0234가되도록 14자를 출력해야했습니다),

parsename, reversecast as int후행 0을 제거하기 위해 사용했습니다 .

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

(그런 다음 내 선행 0을 얻으려면 위의 길이에 따라 올바른 수의 0을 복제하고이를 위의 앞쪽에 연결할 수 있습니다)

나는 이것이 누군가에게 도움이되기를 바랍니다.


@Protiguous 소수점이 1 개이므로 2.5500은 <schema_name>. <object_name>처럼 읽습니다. 두 번째 매개 변수 2는 스키마 이름을 리턴하고 두 번째 매개 변수 1은 오브젝트 이름을 리턴합니다. 일반적으로 PARSENAME ( 'dbo.TableName', 2)과 같이 dbo를 반환하거나 PARSENAME ( 'dbo.TableName', 1)을 사용하여 TableName을 반환합니다.
알리

안녕하세요 .. 귀하의 의견에 내 별칭이 표시되어 있습니다. 왜 그런지 모르겠어요?
Protiguous

2020 년 5 월 26 일 제게 질문 한 정확한 질문은 "파스 네임이 여기서 어떻게 작동해야하나요 ???"였습니다. 답장하는 데 시간이 너무 오래 걸려 죄송합니다.
알리

1

TSQL에서 선행 및 후행 0을 제거 할 수 있습니다.

  1. 문자열이 아닌 경우 STR TSQL 함수를 사용하여 문자열로 변환 한 다음

  2. 선행 및 후행 0 제거

    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 진수가 아니면 0도 트리밍됩니다. CHARINDEX ( '.', @ Number)! = 1은이를 테스트합니다.
Muflix

내 이전 소수점 수표가 잘못되었습니다. 여기가 더 좋습니다 : Select 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 (영)을 대체하지 않습니까? 교체가 끝에서 작동한다고 생각하지
마십시오

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

이 시도.

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

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

-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는 후행 0을 제거하도록 요청합니다.
japzdivino

-1

DECIMAL (9,6) 열은 정밀도 손실없이 float로 변환되므로 CAST (... AS float)가 트릭을 수행합니다.


@HLGEM : float는 숫자를 저장하는 데 적합하지 않으며 "Never use float"는 정확하지 않다고 말합니다. 숫자 만 알면됩니다. 예를 들어 온도 측정은 float로 잘 진행됩니다.

@abatishchev 및 @japongskie : 필요하지 않은 경우 SQL 저장 procs 및 함수 앞에 접두사를 사용하는 것이 좋습니다. 언급 한 링크는 사용하지 않아야하는 저장 프로 시저에 "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.