developer tip

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

optionbox 2020. 10. 18. 09:21
반응형

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


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

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

그 0을 제거하는 방법?


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는 소수점으로 소수점을 지정합니다. 분명히 알려진 문제 입니다.)


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이상을 사용하지 마십시오 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에서도 작동합니다.


SELECT CONVERT(DOUBLE PRECISION, [ColumnName])

나는 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#####

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

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


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

인쇄물:

2.55

Cast(20.5500 as Decimal(6,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') 

결과는 고통 스럽지만 위의 답변에서 많은 도움을 받아 거기에 도달했습니다.


가장 좋은 방법은 정밀도를 잃을 가능성이 있으므로 변환하기 전에 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)


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

나는 다음을 사용했다 :

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

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


다른 옵션 ...

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

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

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


소수의 후행 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을 복제하고이를 위의 앞쪽에 연결할 수 있습니다)

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


it is possible to remove leading and trailing zeros in TSQL

  1. Convert it to string using STR TSQL function if not string, Then

  2. Remove both leading & trailing zeros

    SELECT REPLACE(RTRIM(LTRIM(REPLACE(AccNo,'0',' '))),' ','0') AccNo FROM @BankAccount
    
  3. More info on forum.


Try this :

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

Gives 20.55


How about this? Assuming data coming into your function as @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

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

I understand this is an old post but would like to provide SQL that i came up with

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

try this.

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

The easiest way is to CAST the value as FLOAT and then to a string data type.

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

Try this:

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

I know this thread is very old but for those not using SQL Server 2012 or above or cannot use the FORMAT function for any reason then the following works.

Also, a lot of the solutions did not work if the number was less than 1 (e.g. 0.01230000).

Please note that the following does not work with negative numbers.

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') 

Returns 10.012345 and 0.012345 respectively.


Try this:

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

A DECIMAL(9,6) column will convert to float without loss of precision, so CAST(... AS float) will do the trick.


@HLGEM: saying that float is a poor choice for storing numbers and "Never use float" is not correct - you just have to know your numbers, e.g. temperature measurements would go nicely as floats.

@abatishchev and @japongskie: prefixes in front of SQL stored procs and functions are still a good idea, if not required; the links you mentioned only instructs not to use the "sp_" prefix for stored procedures which you shouldn't use, other prefixes are fine e.g. "usp_" or "spBob_"

Reference: "All integers with 6 or fewer significant decimal digits can be converted to an IEEE 754 floating-point value without loss of precision": https://en.wikipedia.org/wiki/Single-precision_floating-point_format

참고URL : https://stackoverflow.com/questions/2938296/remove-trailing-zeros-from-decimal-in-sql-server

반응형